
import pprint, re
import lacuna.bc

class Empire(lacuna.bc.LacunaObject):
    """ A generic Empire object that can be used with a non-logged-in Guest."""

    path = 'empire'

    ### All of these relate to creating a new empire.  I don't see any burning 
    ### need to create a new empire with Python, and the thought of testing 
    ### this out by creating a bunch of new empires is making me sad.  So I'm 
    ### punting.
    def create(self, *args, **kwargs):
        """ Unimplemented.  It's assumed nobody is going to use MontyLacuna to 
        create a new empire.
        """
        raise NotImplementedError( "Creating an empire is not implemented." )
    def found(self, *args, **kwargs):
        """ Unimplemented.  It's assumed nobody is going to use MontyLacuna to 
        create a new empire.
        """
        raise NotImplementedError( "Founding an empire is not implemented." )
    def update_species(self, *args, **kwargs):
        """ Unimplemented.  It's assumed nobody is going to use MontyLacuna to 
        create a new empire.
        """
        raise NotImplementedError( "Updating a species is not implemented." )

    @lacuna.bc.LacunaObject.call_guest_meth
    def fetch_captcha( self, *args, **kwargs ):
        """ Get location of a captcha puzzle to solve.
        
        There also exists a Captcha class, which requires the user to already 
        be logged in.  This fetch_captcha method exists to allow a brand new, 
        not-yet-logged-in user to get a captcha, the solution to which they 
        can pass to :meth:`create`.

        Since :meth:`create` is unimplemented, you should probably never use 
        this for anything.

        If you're looking for a captcha for anything other than new user 
        creation, go use the Captcha class.

        Returns dict containing 'guid' and 'url' keys.
        """
        return kwargs['rslt']


class MyEmpire( Empire ):
    """ The Empire object belonging to the current Member's empire.
    
    Object Attributes::

        id                      "xxxx",
        rpc_count               321,        # the number of calls made to the server
        is_isolationist         1,          # hasn't sent out probes or colony ships
        name                    "The Syndicate",
        status_message          "A spy's work is never done.",
        home_planet_id          "id-goes-here",
        has_new_messages        4,
        latest_message_id       1234,
        essentia                0,
        planets                 Dict of all of the bodies that belong to you, 
                                keyed off ID.  This includes both colonies and 
                                space stations.
                                {   "id-goes-here" : "Earth",
                                    "id-goes-here" : "Mars",  
                                    "id-goes-here" : "ISS",  
                                    "id-goes-here" : "Halo",  },
        planet_names            The reverse of planets; a dict keyed on the name.
        colonies                Dict of just your colonies, keyed off ID.
                                {   "id-goes-here" : "Earth",
                                    "id-goes-here" : "Mars",  },
        colony_names            The reverse of colonies; a dict keyed on the name.
        stations                Dict of just your space stations, keyed off ID.
                                {   "id-goes-here" : "ISS",
                                    "id-goes-here" : "Halo",  },
        station_names           The reverse of stations; a dict keyed on the name.
        tech_level"             20,         # Highest level university has gotten to.
        self_destruct_active    0,
        self_destruct_date      ""
    """

    pp = pprint.PrettyPrinter( indent = 4 )

    ### These appear in clients.py, not here:
    ###     login()
    ###     send_password_reset_message()
    ###
    ### Involves email, which the server isn't producing, so skipping:
    ###     reset_password()

    @lacuna.bc.LacunaObject.call_member_meth
    def logout( self, *args, **kwargs ):
        pass

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def get_status( self, *args, **kwargs ):
        """ Gets your empire's current status information.

        There shouldn't ever be a need to call this.  Empire status data gets 
        returned with every empire method call, and the current :class:`MyEmpire` 
        object's attributes get updated each time as a result.
        """
        pass

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def get_invite_friend_url( self, *args, **kwargs ):
        """ Get a unique URL you can send to a friend to use to sign up.  Your 
        empire will receive rewards for each friend who joins using such a 
        URL.
        
        Returns a dict including the key ``referral_url``.
        """
        pass

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def invite_friend( self, email:str, message:str = '', *args, **kwargs ):
        """ Sends email to a friend inviting them to join the game.

        Args:
            email (str): The email address to send the invitation to
            message (str):An optional personal message to include.
        Raises:
            lacuna.exceptions.ServerError: 1010 if you have not set 
                up an email address of your own in your profile.
        """
        pass

    @lacuna.bc.LacunaObject.call_returning_meth
    def view_profile( self, *args, **kwargs ):
        """ View your own empire's profile.  Requires login with your real, not 
        sitter, password,

        Returns:
            lacuna.empire.OwnProfile: Your profile
        Raises:
            lacuna.exceptions.ServerError: 1015 ("Sitters cannot 
                modify preferences") if the user is logged in with their sitter.
        """
        return OwnProfile(self.client, kwargs['rslt']['profile'])

    @lacuna.bc.LacunaObject.call_returning_meth
    def view_public_profile( self, empire_id:int, *args, **kwargs ):
        """ View public profile info on any empire.

        Args:
            empire_id (int): ID of the empire to view.
        Returns:
            lacuna.empire.PublicProfile: Requested empire's profile
        """
        return PublicProfile(self.client, kwargs['rslt']['profile'])

    @lacuna.bc.LacunaObject.call_member_meth
    def edit_profile( self, profile:dict, *args, **kwargs ):
        ### The rv does contain a 'status' dict, but it's in a different 
        ### format from what's expected, so skip the set_empire_status 
        ### decorator.
        """ Edit your empire's profile.  Requires that you're logged in with 
        your real, not sitter, password.

        Args:
            profile (dict): With the keys:

                - description
                - email
                - sitter_password
                - status_message
                - city
                - country
                - notes
                - skype
                - player_name
                - public_medals (list of medal IDs to display)
                - skip_happiness_warnings
                - skip_resource_warnings
                - skip_pollution_warnings
                - skip_medal_messages
                - skip_facebook_wall_posts
                - skip_found_nothing
                - skip_excavator_resources
                - skip_excavator_glyph
                - skip_excavator_plan
                - skip_spy_recovery
                - skip_probe_detected
                - skip_attack_messages
                - skip_incoming_ships

        The skip_* keys are booleans, and require 1 for "on" or 0 for "off".
        """
        pass

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def change_password( self, password:str, confirm:str, *args, **kwargs ):
        """ Changes your full password.

        Args:
            password (str): the desired new password
            confirm (str): the same string as 'password'
        """
        self.client.password = password

    @lacuna.bc.LacunaObject.call_returning_meth
    def find( self, name_segment:str, *args, **kwargs ):
        """ Find an empire by name.

        Args::
            name_segment (str): :ref:`Standard TLE search string <gloss_std_search_string>`.
        Returns:
            lacuna.empire.FoundEmpire: list
        """
        mylist = []
        for i in kwargs['rslt']['empires']:
            mylist.append( FoundEmpire(self.client, i) )
        return mylist

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def set_status_message( self, message:str, *args, **kwargs ):
        """ Sets your empire status message.

        Args:
            message (str): The message to set as your empire's profile's status.
        """
        self.status_message = message
        pass

    @lacuna.bc.LacunaObject.call_returning_meth
    def view_boosts( self, *args, **kwargs ):
        """ Shows your current boosts and their expiration dates.
        
        Returns:
            lacuna.empire.Boosts: Current boosts
        """
        return Boosts( self.client, kwargs['rslt']['boosts'] )

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def boost_storage( self, *args, **kwargs ):
        """ Spends 5 E to set a +25% storage boost for one week. """
        pass

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def boost_food( self, *args, **kwargs ):
        """ Spends 5 E to set a +25% food boost for one week. """
        pass

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def boost_water( self, *args, **kwargs ):
        """ Spends 5 E to set a +25% water boost for one week. """
        pass

    @lacuna.bc.LacunaObject.set_empire_status
    @lacuna.bc.LacunaObject.call_member_meth
    def boost_energy( self, *args, **kwargs ):
        """ Spends 5 E to set a +25% energy boost for one week. """
        pass

    @lacuna.bc.LacunaObject.set_empire_status