from typing import Union, Optional
from urllib.parse import urlparse
from io import BytesIO
from time import time
import tarfile
import json
import sys


class BasicTool:
    def __init__(self):
        self.results = []

    def add_result(self, cname: str, cdata: str, dname: Optional[str] = None, data: Optional[dict] = None):
        self.results.append((cname, cdata, dname, data))

    def save(self, result_path: str = "ciphers.tar"):
        assert self.results, "Can't output empty 'ciphers.tar' file!"
        with tarfile.open(result_path, "w") as tfile:
            for cname, cdata, dname, data in self.results:
                self._add_pair(tfile, cname, cdata, dname, data)

    def _add_pair(self, tfile, cname, cdata, dname, data):
        # Encoding cipher query.
        encoded = cdata.encode()
        tinfo = tarfile.TarInfo(name=cname)
        tinfo.mtime = time()
        tinfo.size = len(encoded)
        # Add cipher to tarfile.
        tfile.addfile(tinfo, BytesIO(encoded))

        if dname and data:
            # Encoding repo data.
            encoded = json.dumps(data).encode()
            tinfo = tarfile.TarInfo(name=dname)
            tinfo.mtime = time()
            tinfo.size = len(encoded)
            # Add cipher to tarfile.
            tfile.addfile(tinfo, BytesIO(encoded))

    @staticmethod
    def parse_url(source: str):
        if not source.startswith("http"):
            source = f"http://{source}"
        parsed = urlparse(source)
        return parsed

    @classmethod
    def read_input(cls, entity_path: str = "entity.json"):
        # TODO: Proper argparse here.
        if len(sys.argv) == 2:
            url = sys.argv[1]
        else:
            with open("entity.json") as entity_file:
                data = json.load(entity_file)
            url = data["item"]["URL"]
        # Returning already parsed object.
        return url, cls.parse_url(url)

