# AUTOGENERATED! DO NOT EDIT! File to edit: 05_upload.ipynb (unless otherwise specified).

__all__ = ['Uploader']

# Cell
import requests
import pathspec
import time
from pathlib import Path, PurePosixPath
from .lookup import Lookup
from .conf import CLI_ENDPOINT

# Cell
class Uploader(Lookup):
    path = "."
    project_id = ""
    version = ""
    api = CLI_ENDPOINT
    api_path = "/project/version/upload/sign"

    def __init__(self,
                 path,
                 project_id=None,
                 version=None,
                *args, **kwargs):
        api = None
        if "api" in kwargs:
            api = kwargs.pop("api")
        super().__init__(*args, **kwargs)
        if api != None:
            self.api = api
        upload_path = Path(path)
        if not upload_path.exists():
            raise Exception(f"{upload_path} is not a valid path on your system. Please try again")
        self.path = upload_path

        self.endpoint = f"{self.api}{self.api_path}"
        if "v" in f"{version}":
            version = version.replace("v", "")
            try:
                version = int(version)
            except:
                raise Exception("Version must be a number or in the format v1, v2, v3, and so on.")
        self.version = version
        self.project_id = project_id

    def get_tightignore_paths(self):
        current_dir = Path(self.path)
        tightignore = current_dir / ".tightignore"
        if not tightignore.exists():
            return []
        with open(tightignore, 'r') as fh:
            spec = pathspec.PathSpec.from_lines('gitwildmatch', fh.readlines())
            matches = spec.match_tree(self.path)
            match_list = []
            for m in matches:
                match_path = str(PurePosixPath(Path(m)))
                match_list.append(match_path)
            return match_list

    def destination_path(self, relative_path):
        relative_path = relative_path.replace("\\", "/")
        return f"{self.project_id}/v{self.version}/app/{relative_path}"

    def sign_dir(self):
        path = self.path
        default_glob = path.rglob("*")
        ignore_paths = self.get_tightignore_paths()
        dir_files = [x for x in default_glob if x.is_file()]
        dir_file_paths = [str(PurePosixPath(x.relative_to(path))) for x in dir_files]
        final_paths = [x for x in dir_file_paths if x not in ignore_paths]
        destination_paths = [self.destination_path(x) for x in final_paths]
        return destination_paths, final_paths

    def upload(self, verbose=0, dry_run=False, dry_sign=False):
        if verbose == 1:
            print("Uploading...")
        files_uploaded_count = 0
        destination_paths, local_files = self.sign_dir()
        data = {
            "files": destination_paths,
            "project_id": self.project_id,
            "version": self.version
        }
        if dry_run:
            for f in local_files:
                files_uploaded_count += 1
                dest_path = self.destination_path(f)
                _dir = Path(self.path)
                f_path = _dir / f
                print("Dry run uploading... ", f_path)
                time.sleep(0.8)
                print('..done')
        else:
            # sign_r = requests.post(self.endpoint, json=data)
            sign_r = self.http_post(self.endpoint, data=data)
            self.handle_invalid_lookup(sign_r, expected_status_code=200)
            signed_response = sign_r.json()
            keys = list(signed_response.keys())
            if len(keys) != 2:
                raise Exception("Upload failed. Please contact us for furhter information. Code 3122-3129091389892")
            signed_data = dict(zip(signed_response["files"], signed_response["signed"]))
            for f in local_files:
                dest_path = self.destination_path(f)
                signed_url = signed_data[dest_path]
                _dir = Path(self.path)
                f_path = _dir / f
                print("Uploading", f, '...')
                r2 = requests.post(signed_url, files={'file': open(f_path, 'rb')})
                if r2.status_code == 204:
                    files_uploaded_count += 1
                else:
                    if verbose == 1:
                        print(f, 'was not uploaded successfully')
        print(f"{files_uploaded_count} files uploaded.")
        return files_uploaded_count