# -*- coding: UTF-8 -*-
# Copyright 2020 by Kurt Rathjen. All Rights Reserved.
#
# This library is free software: you can redistribute it and/or modify it 
# under the terms of the GNU Lesser General Public License as published by 
# the Free Software Foundation, either version 3 of the License, or 
# (at your option) any later version. This library is distributed in the 
# hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
# See the GNU Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.

import os
import logging

from studiolibrarymaya import baseitem

try:
    import mutils
    import mutils.gui
    import maya.cmds
except ImportError as error:
    print(error)


logger = logging.getLogger(__name__)


def save(path, *args, **kwargs):
    """Convenience function for saving an AnimItem."""
    AnimItem(path).safeSave(*args, **kwargs)


def load(path, *args, **kwargs):
    """Convenience function for loading an AnimItem."""
    AnimItem(path).load(*args, **kwargs)


class AnimItem(baseitem.BaseItem):

    NAME = u"动画"
    EXTENSION = ".anim"
    ICON_PATH = os.path.join(os.path.dirname(__file__), "icons", "animation.png")
    TRANSFER_CLASS = mutils.Animation

    def imageSequencePath(self):
        """
        Return the image sequence location for playing the animation preview.

        :rtype: str
        """
        return self.path() + "/sequence"

    def loadSchema(self):
        """
        Get schema used to load the animation item.

        :rtype: list[dict]
        """
        schema = super(AnimItem, self).loadSchema()

        anim = mutils.Animation.fromPath(self.path())

        startFrame = anim.startFrame() or 0
        endFrame = anim.endFrame() or 0

        value = "{0} - {1}".format(startFrame, endFrame)
        schema.insert(3, {"name": "frameRange", "title": u"帧范围", "value": value})

        schema.extend([
            {
                "name": "optionsGroup",
                "title": u"导入选项",
                "type": "group",
                "order": 2,
            },
            {
                "name": "connect",
                "title": u"连接",
                "type": "bool",
                "inline": True,
                "default": False,
                "persistent": True,
                "label": {"name": ""}
            },
            {
                "name": "currentTime",
                "type": "bool",
                "title": u"从当前帧开始",
                "inline": True,
                "default": True,
                "persistent": True,
                "label": {"name": ""}
            },
            {
                "name": "sourceTime",
                "title": u"范围",
                "type": "range",
                "default": [startFrame, endFrame],
            },
            {
                "name": "option",
                "title": u"选项",
                "type": "enum",
                "default": u"替换全部",
                "items": [u"替换", u"替换全部", u"插入", u"合并"],
                "persistent": True,
            },
        ])

        return schema

    def load(self, **kwargs):
        OPTION_MAPPING = {
        u"替换": "replace",
        u"替换全部": "replace all",
        u"插入": "insert",
        u"合并": "merge"
        }
        """
        Load the animation for the given objects and options.

        :type kwargs: dict
        """
        anim = mutils.Animation.fromPath(self.path())
        # 获取用户选择的选项，并将其转换为英文
        option = kwargs.get("option")
        if option in OPTION_MAPPING:
            option = OPTION_MAPPING[option]
        anim.load(
            objects=kwargs.get("objects"),
            namespaces=kwargs.get("namespaces"),
            attrs=kwargs.get("attrs"),
            startFrame=kwargs.get("startFrame"),
            sourceTime=kwargs.get("sourceTime"),
            option=option,
            connect=kwargs.get("connect"),
            mirrorTable=kwargs.get("mirrorTable"),
            currentTime=kwargs.get("currentTime")
        )

    def saveSchema(self):
        """
        Get the schema for saving an animation item.

        :rtype: list[dict]
        """
        start, end = (1, 100)

        try:
            start, end = mutils.currentFrameRange()
        except NameError as error:
            logger.exception(error)

        return [
            {
                "name": "folder",
                "type": "path",
                "layout": "vertical",
                "visible": False,
            },
            {
                "name": u"name",
                "title": u"名称",
                "type": "string",
                "layout": "vertical"
            },
            {
                "name": "fileType",
                "title": u"储存格式",
                "type": "enum",
                "layout": "vertical",
                "default": "mayaAscii",
                "items": ["mayaAscii", "mayaBinary"],
                "persistent": True
            },
            {
                "name": "frameRange",
                "title": u"帧范围",
                "type": "range",
                "layout": "vertical",
                "default": [start, end],
                "actions": [
                    {
                        "name": "按时间轴",
                        "callback": mutils.playbackFrameRange
                    },
                    {
                        "name": "按选中时间范围",
                        "callback": mutils.selectedFrameRange
                    },
                    {
                        "name": "按选择对象",
                        "callback": mutils.selectedObjectsFrameRange
                    },
                ]
            },
            {
                "name": "byFrame",
                "title": u"帧采样",
                "type": "int",
                "default": 1,
                "layout": "vertical",
                "persistent": True
            },
            {
                "name": "comment",
                "title": u"备注",
                "type": "text",
                "layout": "vertical"
            },
            {
                "name": "bakeConnected",
                "title": u"烘焙连接",
                "type": "bool",
                "default": False,
                "persistent": True,
                "inline": True,
                "label": {"visible": False}
            },
            {
                "name": "objects",
                "type": "objects",
                "label": {
                    "visible": False
                }
            },
        ]

    def saveValidator(self, **kwargs):
        """
        The save validator is called when an input field has changed.

        :type kwargs: dict
        :rtype: list[dict]
        """
        fields = super(AnimItem, self).saveValidator(**kwargs)

        # Validate the by frame field
        if kwargs.get("byFrame") == '' or kwargs.get("byFrame", 1) < 1:
            fields.extend([
                {
                    "name": "byFrame",
                    "error": u"帧采样不能小于1!"
                }
            ])

        # Validate the frame range field
        start, end = kwargs.get("frameRange", (0, 1))
        if start >= end:
            fields.extend([
                {
                    "name": "frameRange",
                    "error":  u"开始帧不能大于或等于结束帧!"
                }
            ])

        # Validate the current selection field
        objects = kwargs.get("objects")
        if objects and mutils.getDurationFromNodes(objects, time=[start, end]) <= 0:
            fields.extend([
                {
                    "name": "objects",
                    "error": u"在选定对象上没有找到动画/s!\n请做个动画吧!",
                }
            ])

        return fields

    def save(self, objects, sequencePath="", **kwargs):
        """
        Save the animation from the given objects to the item path.
        
        :type objects: list[str]
        :type sequencePath: str
        :type kwargs: dict
        """
        super(AnimItem, self).save(**kwargs)

        # Save the animation to the given path location on disc
        mutils.saveAnim(
            objects,
            self.path(),
            time=kwargs.get("frameRange"),
            fileType=kwargs.get("fileType"),
            iconPath=kwargs.get("thumbnail"),
            metadata={"description": kwargs.get("comment", "")},
            sequencePath=sequencePath,
            bakeConnected=kwargs.get("bakeConnected")
        )
