from audiostack.helpers.request_interface import RequestInterface
from audiostack.helpers.request_types import RequestTypes
from audiostack.helpers.api_item import APIResponseItem
from audiostack.helpers.api_list import APIResponseList


class Mix:
    interface = RequestInterface(family="production")

    class Item(APIResponseItem):
        def __init__(self, response) -> None:
            super().__init__(response)
            self.productionId = self.data["productionId"]

        def download(self, fileName="", path="./") -> None:
            sections = self.data["files"]
            for i, s in enumerate(sections):
                format = s["format"]
                if not fileName:
                    full_name = f"default_mix.{format}"
                else:
                    full_name = f"{fileName}.{format}"

                RequestInterface.download_url(
                    s["url"], destination=path, name=full_name
                )

        def delete(self):
            return Mix.delete(self.productionId)

    class List(APIResponseList):
        def __init__(self, response, list_type) -> None:
            super().__init__(response, list_type)

        def resolve_item(self, list_type, item):
            if list_type == "productionIds":
                return Mix.Item({"data": item})
            else:
                raise Exception()

    @staticmethod
    def create(
        speechId="",
        speechItem=None,
        soundTemplate: str = "",
        forceLength: float = 0.0,  # a value of 0 means no force length
        mediaFiles: dict = {},
        sectionProperties: dict = {},
        masteringPreset: str = "",
        acousticSpace: str = "",
        callbackUrl: str = "",
        public: bool = False,
    ) -> Item:
        if speechId and speechItem:
            raise Exception("speechId or scriptItem should be supplied not both")
        if not (speechId or speechItem):
            raise Exception("speechId or scriptItem should be supplied")
        if speechItem:
            speechId = speechItem.speechId

        if not isinstance(soundTemplate, str):
            raise Exception("soundTemplate argument should be a string")
        if not isinstance(forceLength, float):
            raise Exception("forceLength should be a float")
        if not isinstance(masteringPreset, str):
            raise Exception("masteringPreset should be a string")
        if not isinstance(acousticSpace, str):
            raise Exception("acousticSpace should be a string")

        body = {
            "speechId": speechId,
            "soundTemplate": soundTemplate,
            "forceLength": forceLength,
            "mediaFiles": mediaFiles,
            "sectionProperties": sectionProperties,
            "masteringPreset": masteringPreset,
            "acousticSpace": acousticSpace,
            "callbackUrl": callbackUrl,
            "public": public,
        }

        r = Mix.interface.send_request(rtype=RequestTypes.POST, route="mix", json=body)
        if r["statusCode"] == 202:
            print("Response in progress please wait...")
            return Mix.get(Mix.Item(r).productionId)
        
        return Mix.Item(r)

    @staticmethod
    def get(productionId: str) -> Item:
        r = Mix.interface.send_request(
            rtype=RequestTypes.GET, route="mix", path_parameters=productionId
        )
        return Mix.Item(r)

    @staticmethod
    def delete(productionId: str) -> str:
        r = Mix.interface.send_request(
            rtype=RequestTypes.DELETE, route="mix", path_parameters=productionId
        )
        return APIResponseItem(r)

    @staticmethod
    def list(
        projectName="", moduleName: str = "", scriptName: str = "", scriptId: str = ""
    ) -> list:
        query_params = {
            "projectName": projectName,
            "moduleName": moduleName,
            "scriptName": scriptName,
            "scriptId": scriptId,
        }

        r = Mix.interface.send_request(
            rtype=RequestTypes.GET, route="mixes", query_parameters=query_params
        )
        return Mix.List(r, list_type="productionIds")
