# pylint: disable=W0312,R0913
import requests, json
from pyonep.portals.constants import HTTP_STATUS
from pyonep.portals.endpoints import Endpoints
from pyonep.portals.utils import dictify_device_meta,\
                                 stringify_device_meta
from getpass import getpass
import sys

if sys.version_info[0] < 3:
    _input = raw_input
else:
    _input = input

class Portals(Endpoints):
    def __init__(   self,
                    domain,
                    portal_name,
                    user,
                    auth='__prompt__',
                    use_token=False,
                    debug=False):
        """
            Params:
                domain:         the domain of the Exosite domain your Portal is on. 
                                i.e. mydomain.exosite.com
                portal_name:    the name of the Exosite Portal. i.e. 'My Device Portal'
                user:           typically, the email address you use to logon to Portals 
                                or your Portals user name
                auth:           if left blank, the creator of the Portals object will 
                                be prompted for their Portals password if specifying the 
                                auth parameter, it should be either the user password or a 
                                Portals token
                use_token:      if using a token in the auth parameter, set this to True. 
                                Otherwise, leave blank
        """
        if auth == '__prompt__':
            print('') # some interpreters don't put a newline before the getpass prompt
            auth = getpass('Enter User Password: ')
        else:
            auth = auth
        Endpoints.__init__(   self, 
                            domain,
                            portal_name,
                            user,
                            auth,
                            use_token=use_token
        )

    def get_portals_list(self):
        """     Method to return a list of Portal names with their id's. 
        
            Returns list of tuples as [(id_1, portal_name1), (id_2, portal_name2)]
        """
        portal_ids = self.get_domain_portal_ids()
        portals = [ (p, self.get_portal_by_id(p)) for p in portal_ids ]
        return [ (p[0], p[1]['info']['description']['name'], p) for p in portals ]

    def user_portals_picker(self):
        """
            This function is broken and needs to either be fixed or discarded.

            User-Interaction function. Allows user to choose which Portal
            to make the active one.
        """
        # print("Getting Portals list. This could take a few seconds...")
        portals = self.get_portals_list()
        done = False
        while not done:
            opts = [ (i, p) for i, p in enumerate(portals) ]
            # print('')
            for opt, portal in opts:
                print("\t{0} - {1}".format(opt, portal[1]))
            # print('')
            valid_choices = [o[0] for o in opts]
            choice = _input("Enter choice ({0}): ".format(valid_choices) )
            if int(choice) in valid_choices:
                done = True

                # loop through all portals until we find an 'id':'rid' match
                self.set_portal_name( opts[int(choice)][1][1] )
                self.set_portal_id( opts[int(choice)][1][0] )
                # self.set_portal_rid( opts[int(choice)][1][2][1]['info']['key'] )
                # self.__portal_sn_rid_dict = opts[int(choice)][1][2][1]['info']['aliases']

            else:
                print("'{0}' is not a valid choice. Please choose from {1}".format(
                    choice, valid_choices))


    def get_portal_by_name(self, portal_name):
        """
            Set active portal according to the name passed in 'portal_name'.

            Returns dictionary of device 'serial_number: rid'
        """
        portals = self.get_portals_list()

        for p in portals:
            # print("Checking {!r}".format(p))
            if portal_name == p[1]:
                # print("Found Portal!")
                self.set_portal_name( p[1] )
                self.set_portal_id( p[0] )
                self.set_portal_cik( p[2][1]['info']['key'] )
                # print("Active Portal Details:\nName: {0}\nId: {1}\nCIK: {2}".format(
                #                               self.portal_name(),
                #                               self.portal_id(),
                #                               self.portal_cik()))
                return p
        return None

    @classmethod
    def login_to_portal(cls,
                        domain=None,
                        portal_name=None,
                        user=None,
                        credential=None,
                        use_token=False,
                        portal_id=None,
                        # portal_rid=None,
                        get_devices=False,
                        debug=False):
        """
            A classmethod that returns a (token, Portals object) tuple.

            This method can be interactive based on the input arguments.

            Sets up the Portals object with all the member variables
            it needs to make future api calls. It basically just calls 
            Portals.get_portal_by_name(), but instead of returning a 
            Portals object, it returns a Portals() object.

            This is a convenience function that can be called at the 
            time of instantiation.

            Instantiate the Portals object with user/password authentication
            then call this function. The resultant object will be a Portals
            object that uses token authentication for all future calls 
            instead of using user/password credentials.

            Examples:
                # for interactive mode, get a password prompt, a token 
                # and a logged-in Portals object
                token, B = Portals.login_to_portal( domain=<domain>,
                                                     portal_name=<portal>,
                                                     user=<user/email>
                )

                # for non-interactive mode, passing in user password to 
                # get a token and a logged-in Portals object
                token, B = Portals.login_to_portal( domain=<domain>,
                                                     portal_name=<portal>,
                                                     user=<user/email>,
                                                     credential=<password>
                )

                # for non-interactive mode, passing in token to get a 
                # logged-in Portals object
                token, B = Portals.login_to_portal( domain=<domain>,
                                                     portal_name=<portal>,
                                                     user=<user/email>,
                                                     credential=<token>,
                                                     use_token=True
                )

                # for non-interactive mode, passing in token and id 
                # to get a Portals object that doesn't need to make any 
                # Portals API calls. 
                token, B = Portals.login_to_portal( domain=<domain>,
                                                     portal_name=<portal>,
                                                     user=<user/email>,
                                                     credential=<token>,
                                                     use_token=True,
                                                     portal_id=<portal_id>,
                                                     portal_rid=<portal_rid>
                )
        """
        if domain is None:
            domain = _input("Enter domain: ")
        if portal_name is None:
            portal_name = _input("Enter name of Portal: ")
        if user is None:
            user = _input("Enter username: ")
        if None is credential:
            # interactive mode
            B = Portals(   domain=domain,
                            portal_name=portal_name,
                            user=user,
                            debug=debug
            )
            token = B.get_user_token()
            # print("Got token {0}".format(token))
        elif not None is credential and not use_token:
            # non-interactive, using a user-password to retrieve token
            B = Portals(   domain=domain,
                            portal_name=portal_name,