# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os.path
import pathlib

from enum import Enum, IntEnum
from typing import List, Optional, Dict
from api.v1 import api_pb2

from pydantic import BaseModel, Extra, Field, validator, root_validator, HttpUrl

from config import RepoProps


class ComplexityEnum(str, Enum):
    BASIC = "BASIC"
    MEDIUM = "MEDIUM"
    ADVANCED = "ADVANCED"


class DatasetFormat(str, Enum):
    JSON = "json"
    AVRO = "avro"


class DatasetLocation(str, Enum):
    LOCAL = "local"


class Dataset(BaseModel):
    format: DatasetFormat
    location: DatasetLocation
    file_name: str = ""


class Topic(BaseModel):
    id: str
    source_dataset: str


class EmulatorType(str, Enum):
    KAFKA = "kafka"


class Emulator(BaseModel):
    type: EmulatorType
    topic: Topic


class ImportFile(BaseModel):
    name: str = Field(..., min_length=1)
    context_line: int = 0
    content: str = ""


class Tag(BaseModel):
    """
    Tag represents the beam-playground embedded yaml content
    """

    # These parameters are parsed from YAML and are required:

    categories: List[str] = []
    """
    Titles of categories to list this snippet in. Non-existent categories will be created.
    """

    complexity: ComplexityEnum
    """
    How hard is the snippet to understand.
    """

    context_line: int = 1
    """
    The line number to scroll to when the snippet is loaded.
    This applies after the metadata block is removed from the file, so discount for those lines.
    Integer, 1-based.
    """

    description: str
    """
    Description text to show on mouse over.
    """

    name: str = Field(..., min_length=1)
    """
    Name to show in the dropdown and to compose snippet ID from.
    """

    # These parameters are parsed from YAML and are optional:

    datasets: Dict[str, Dataset] = {}
    """
    Datasets which will be used by emulators. Example:
    datasets:
      CountWords:
        location: local
        format: json
    """

    default_example: bool = False
    """
    Whether this is the default example in its SDK.
    If multiple snippets set this to `true` the behavior is undefined.
    """

    emulators: List[Emulator] = []
    """
    List of emulators to start during pipeline execution. Currently only `kafka` type is supported.
    Example:
    emulators:
      - type: kafka
        topic:
          id: dataset
          source_dataset: CountWords
    """

    always_run: bool = False
    """
    The example output will not be cached and playground will always run its code when user clicks 'Run' if this is set to 'True'
    """

    never_run: bool = False
    """
    If 'True', it will not be possible to run this example from Playground UI. It will be read-only.
    """


    multifile: bool = False
    """
    Whether this is a file of a multi-file example.
    """

    pipeline_options: str = ""
    """
    Pipeline options. Example:
    pipeline_options: --name1 value1 --name2 value2
    """

    tags: List[str] = []
    """
    Tags by which this snippet can be found in the dropdown.
    """

    url_notebook: Optional[HttpUrl] = None
    """
    The URL of the Colab notebook that is based on this snippet.
    """

    # These parameters are NOT parsed from YAML but are added at construction:

    filepath: str = Field(..., min_length=1)
    files: List[ImportFile] = []
    line_start: int
    line_finish: int

    class Config:
        supported_categories = []
        extra = Extra.forbid

    @root_validator(skip_on_failure=True)
    def lines_order(cls, values):
        assert (
            (0 <= values["line_start"] < values["line_finish"]) and
              (values["context_line"] <= values["line_start"] or values["context_line"] > values["line_finish"])
        ), f"line ordering error: {values}"
        return values

    @root_validator(skip_on_failure=True)
    def datasets_with_emulators(csl, values):
        if values.get("datasets") and not values.get("emulators"):
            raise ValueError("datasets w/o emulators")
        return values

    @validator("emulators", each_item=True)
    def dataset_defined(cls, v, values, **kwargs):
        if "datasets" not in values:
            raise ValueError("datasets not defined")
        for dataset_id in values["datasets"]:
            if dataset_id == v.topic.source_dataset:
                return v
        raise ValueError(
            f"Emulator topic {v.topic.id} has undefined dataset {v.topic.source_dataset}"
        )

    @validator("datasets")
    def dataset_file_name(cls, datasets):
        for dataset_id, dataset in datasets.items():
            dataset.file_name = f"{dataset_id}.{dataset.format.value}"
            if dataset.location == DatasetLocation.LOCAL:
                dataset_path = os.path.join(
                    RepoProps.REPO_DATASETS_PATH, dataset.file_name
                )
                if not os.path.isfile(dataset_path):
                    logging.error(
                        "File not found at the specified path: %s", dataset_path
                    )
                    raise FileNotFoundError
        return datasets

    @validator("categories", each_item=True)
    def category_supported(cls, v, values, config, **kwargs):
        if v not in config.supported_categories:
            raise ValueError(f"Category {v} not in {config.supported_categories}")
        return v

    @root_validator
    def multifile_files(cls, values):
        if values.get('multifile', False) and not values.get('files', []):
            raise ValueError('multifile is True but no files defined')
        return values

    @validator("filepath")
    def check_filepath_exists(cls, v: str):
        if not os.path.isfile(v):
            logging.error("Example file not found: %s", v)
            raise FileNotFoundError(v)
        return v

    @validator("files", each_item=True)
    def check_files(cls, v: ImportFile, values):
        local_path = os.path.join(os.path.dirname(values["filepath"]), v.name)
        if not os.path.isfile(local_path):
            logging.error("Import file not found: %s", local_path)
            raise FileNotFoundError(local_path)
        v.content = open(local_path).read()
        return v


class SdkEnum(IntEnum):
    JAVA = api_pb2.SDK_JAVA
    GO = api_pb2.SDK_GO
    PYTHON = api_pb2.SDK_PYTHON
    SCIO = api_pb2.SDK_SCIO


def StringToSdkEnum(s: str) -> SdkEnum:
    parsed: int = api_pb2.Sdk.Value(s)
    return SdkEnum(parsed)


class Example(BaseModel):
    """
    Class which contains all information about beam example
    """

    sdk: SdkEnum
    tag: Tag
    filepath: str = Field(..., min_length=1)
    code: str = Field(..., min_length=1)
    url_vcs: HttpUrl
    type: int = api_pb2.PRECOMPILED_OBJECT_TYPE_UNSPECIFIED
    context_line: int = Field(..., gt=0)

    status: int = api_pb2.STATUS_UNSPECIFIED
    logs: str = ""
    pipeline_id: str = ""
    output: str = ""
    compile_output: str = ""
    graph: str = ""
