# 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.


from typing import ClassVar, List, Optional, final

from gravitino.api.rel.indexes.index import Index


class Indexes:
    """Helper methods to create index to pass into Apache Gravitino.

    Attributes:
        EMPTY_INDEXES (List[Index]):
            An empty array of indexes.
        DEFAULT_MYSQL_PRIMARY_KEY_NAME (str):
            MySQL does not support setting the name of the primary key,
            so the default name is used.
    """

    EMPTY_INDEXES: ClassVar[List[Index]] = []
    DEFAULT_MYSQL_PRIMARY_KEY_NAME: ClassVar[str] = "PRIMARY"

    @staticmethod
    def of(
        index_type: Index.IndexType,
        name: Optional[str],
        field_names: List[List[str]],
        properties: Optional[dict[str, str]] = None,
    ) -> Index:
        return Indexes.IndexImpl(index_type, name, field_names, properties or {})

    @staticmethod
    def unique(
        name: str,
        field_names: List[List[str]],
        properties: Optional[dict[str, str]] = None,
    ) -> Index:
        return Indexes.IndexImpl(
            Index.IndexType.UNIQUE_KEY, name, field_names, properties or {}
        )

    @staticmethod
    def primary(
        name: str,
        field_names: List[List[str]],
        properties: Optional[dict[str, str]] = None,
    ) -> Index:
        return Indexes.IndexImpl(
            Index.IndexType.PRIMARY_KEY, name, field_names, properties or {}
        )

    @staticmethod
    def create_mysql_primary_key(
        field_names: List[List[str]], properties: Optional[dict[str, str]] = None
    ) -> Index:
        return Indexes.primary(
            Indexes.DEFAULT_MYSQL_PRIMARY_KEY_NAME, field_names, properties or {}
        )

    @final
    class IndexImpl(Index):
        def __init__(
            self,
            index_type: Index.IndexType,
            name: Optional[str],
            field_names: List[List[str]],
            properties: Optional[dict[str, str]] = None,
        ):
            self._index_type = index_type
            self._name = name
            self._field_names = field_names
            self._properties = properties or {}

        def type(self) -> Index.IndexType:
            return self._index_type

        def name(self) -> Optional[str]:
            return self._name

        def field_names(self) -> List[List[str]]:
            return self._field_names

        def properties(self) -> dict[str, str]:
            return self._properties
