from apispec import BasePlugin
from apispec.exceptions import DuplicateComponentNameError
from ..utils import camelize


class MultiOperationBuilderPlugin(BasePlugin):
    def __init__(self, refs=False):
        self.refs = refs
        self._reserved_keys = ["oneOf", "allOf", "anyOf"]
        self.counter = {"schema": {}, "example": {}}

    def init_spec(self, spec):
        super().init_spec(spec)
        self.spec = spec
        self.duplicate_schemas = {}
        self.duplicate_examples = {}

    def add_ref_schema(self, name, schema):
        # _name = self._get_uniq_refname('schema', name)
        try:
            self.spec.components.schema(name, schema)
        except DuplicateComponentNameError as e:
            name = self._get_uniq_refname("schema", name)
            self.add_ref_schema(name, schema)
        return self.spec.get_ref("schema", name)

    def add_ref_example(self, name, body):
        try:
            self.spec.components.example(name, body)
        except DuplicateComponentNameError as e:
            name = self._get_uniq_refname("example", name)
            self.add_ref_example(name, body)
        return self.spec.get_ref("example", name)

    def _get_uniq_refname(self, key, name):
        if self.counter[key].get(name, None) is None:
            self.counter[key] = {name: 0}
            _name = name
        else:
            self.counter[key][name] += 1
        _name = name + "_" + str(self.counter[key][name] + 1)
        return _name

    def _fix_response_schema(self, path, operations):
        for key, value in operations.items():
            for code, response in value.get("responses", {}).items():
                if "content" in response:
                    for content_type, schema in response["content"].items():
                        opskey = (
                            camelize(path + " " + key + str(code))
                            + content_type
                        )

                        # schemafix
                        if self.duplicate_schemas.get(opskey, None) is None:
                            if self.refs:
                                schema["schema"] = self.add_ref_schema(
                                    "schema"
                                    + camelize(path + " " + key + str(code)),
                                    schema["schema"],
                                )
                            self.duplicate_schemas[opskey] = [schema["schema"]]
                        else:
                            if self.refs:
                                schema["schema"] = self.add_ref_schema(
                                    "schema"
                                    + camelize(path + " " + key + str(code)),
                                    schema["schema"],
                                )
                            self.duplicate_schemas[opskey].append(
                                schema["schema"]
                            )
                            schema["schema"] = dict(
                                oneOf=[
                                    schema
                                    for schema in self.duplicate_schemas.get(
                                        opskey
                                    )
                                ]
                            )
                        # examplefix
                        if "examples" in schema:
                            if (
                                self.duplicate_examples.get(opskey, None)
                                is None
                            ):
                                if self.refs:
                                    for desc, example_item in schema[
                                        "examples"
                                    ].items():
                                        schema["examples"][
                                            desc
                                        ] = self.add_ref_example(
                                            "example"
                                            + camelize(
                                                path + " " + key + str(code)
                                            ),
                                            example_item,
                                        )
                                self.duplicate_examples[opskey] = [
                                    schema["examples"]
                                ]
                            else:
                                if self.refs:
                                    for desc, example_item in schema[
                                        "examples"
                                    ].items():
                                        schema["examples"][
                                            desc
                                        ] = self.add_ref_example(
                                            "example"
                                            + camelize(
                                                path + " " + key + str(code)
                                            ),
                                            example_item,
                                        )
                                self.duplicate_examples[opskey].append(
                                    schema["examples"]
                                )
                                for example in self.duplicate_examples.get(
                                    opskey
                                ):
                                    for (
                                        example_name,
                                        example_value,
                                    ) in example.items():
                                        schema["examples"][
                                            example_name
                                        ] = example_value

    def operation_helper(self, path, operations, **kwargs):
        """Operation helper that add `deprecated` flag if in `kwargs`"""
        self._fix_response_schema(path, operations)
