from __future__ import annotations

import os
import typing as T


from pycs import db
from pycs.database.base import NamedBaseModel
from pycs.database.util import commit_on_return

class Collection(NamedBaseModel):
    """ DB Model for collections """

    # table columns
    project_id = db.Column(
        db.Integer,
        db.ForeignKey("project.id", ondelete="CASCADE"),
        nullable=False)

    reference = db.Column(
        db.String, nullable=False)

    description = db.Column(
        db.String)

    position = db.Column(
        db.Integer, nullable=False)

    autoselect = db.Column(
        db.Boolean, nullable=False)


    # contraints
    __table_args__ = (
        db.UniqueConstraint('project_id', 'reference'),
    )

    # relationships to other models
    files = db.relationship("File", backref="collection", lazy="dynamic")

    serialize_only = NamedBaseModel.serialize_only + (
        "project_id",
        "reference",
        "description",
        "position",
        "autoselect",
    )


    def get_files(self, *filters, offset: int = 0, limit: int = -1):
        """
        get an iterator of files associated with this project

        :param offset: file offset
        :param limit: file limit
        :return: iterator of files
        """

        # pylint: disable=import-outside-toplevel, cyclic-import
        from pycs.database.File import File
        return self.files.filter(*filters).order_by(File.id).offset(offset).limit(limit)

    # pylint: disable=too-many-arguments
    @commit_on_return
    def add_file(self,
                 uuid: str,
                 file_type: str,
                 name: str,
                 extension: str,
                 size: int,
                 filename: str,
                 frames: int = None,
                 fps: float = None) -> T.Tuple["File", bool]:
        """
        add a file to this collection

        :param uuid: unique identifier which is used for temporary files
        :param file_type: file type (either image or video)
        :param name: file name
        :param extension: file extension
        :param size: file size
        :param filename: actual name in filesystem
        :param frames: frame count
        :param fps: frames per second
        :return: file
        """
        # pylint: disable=import-outside-toplevel, cyclic-import
        from pycs.database.File import File

        path = os.path.join(self.project.data_folder, f"{filename}{extension}")


        file, is_new = File.get_or_create(
            project_id=self.project_id, collection_id=self.id, path=path)

        file.uuid = uuid
        file.type = file_type
        file.name = name
        file.extension = extension
        file.size = size
        file.frames = frames
        file.fps = fps

        return file, is_new


    @staticmethod
    def update_autoselect(collections: T.List[Collection]) -> T.List[Collection]:
        """ disable autoselect if there are no elements in the collection """

        found = False

        for collection in collections:
            if not collection.autoselect:
                continue

            if found:
                collection.autoselect = False

            elif collection.files.count() == 0:
                collection.autoselect = False
                found = True

        return collections
