import os
import requests

class Client():
    """All client functions return the response in json format, except for get_file"""

    def __init__(self, email: str, password: str, base_url="https://platform.myxrobotics.com"):
        self.base_url = base_url

        self.session = requests.Session()
        r = self.session.post(f'{self.base_url}/users/login/',
            data={'email': email, 'password': password},
            allow_redirects=False
        )

        if r.headers['location'] != '/dashboard/':
            raise Exception("Failed to authenticate. Check your email and password are correct.")



    def get_file(self, twin_id: int, file_path: str):
        """ Download a file if it exists. Returns a file-like object from which you can read in
        binary mode. Some twin files are generated by MYX."""
        return self.session.get(f'{self.base_url}/twins/{twin_id}/data/{file_path}', stream=True).raw


    def upload_dir(self, directory, show_status=True):
        """ Upload all files in a directory. """
        for root, subdirs, files in os.walk(directory):
            for fn in files:
                path = os.path.join(root, fn)
                if show_status: print(f"Uploading {path}")
                self.upload_file(path)


    def upload_file(self, filename):
        """ Upload a single file from the filesystem. """
        with open(filename, 'rb') as f:
            return self.session.post(f'{self.base_url}/upload/file/', files={'file': f})


    def finish_upload(self, twin_name='Twin from API', client_group=''):
        """ Give a name for the new twin and notify MYX that there will be no more images uploaded.
        This triggers the processing pipeline to start working on your data.
        The first return value is whether or not you had enough balance to complete the upload.
        The second value is the URL you should go to add more money to your account.
        """
        r = self.session.post(f'{self.base_url}/upload/checkout/begin/', json={
            'twinName': twin_name,
            'clientGroup': client_group,
        })

        next_url = r.json()['url']
        if next_url.startswith(f'{self.base_url}/upload/checkout/success/'):
            self.session.get(next_url)
            return True, ''
        else:
            return False, next_url


    def get_annotations(self, twin_id: int):
        """ Get a list of all annotations for a given twin. """
        return self.session.get(f'{self.base_url}/twins/{twin_id}/annotations/').json()


    def make_new_annotation(self, twin_id: int, x: float, y: float, z: float, label: str, iframeURL: str, notes: str):
        """ Make a new annotation at the given position, with the given label,
        url and additional notes. """
        return self.session.post(f'{self.base_url}/twins/{twin_id}/annotations/', json={
            'x': x,
            'y': y,
            'z': z,
            'label': label,
            'iframeURL': iframeURL,
            'notes': notes,
        }).json()


    def get_twins(self) :
        """ Get a list of all twins you own. """
        return self.session.get(f'{self.base_url}/api/list_all/').json()
        #Twin(str(json['id']), json['name'], json['latitude'], json['longitude'], json['captureDate'])
