#!/usr/bin/env python3
# coding=utf-8
"""
synfig_fileformat.py
Synfig file format utilities

Copyright (C) 2011 Nikita Kitaev

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
"""

# ##### Constants ##########################################
kux = 60.0  # Number of SVG units (pixels) per Synfig "unit"
gamma = 1.0
tangent_scale = 3.0  # Synfig tangents are scaled by a factor of 3

# ##### Layer parameters, types, and default values ########
layers = {}

# Layer_Composite is the parent of most layers
default_composite = {
    "z_depth": ["real", 0.0],
    "amount": ["real", 1.0],
    "blend_method": ["integer", 0],
}

layers["PasteCanvas"] = default_composite.copy()
layers["PasteCanvas"].update(
    {
        "origin": ["vector", [0.0, 0.0]],
        "canvas": ["canvas", None],
        "zoom": ["real", 0.0],
        "time_offset": ["time", "0s"],
        "children_lock": ["bool", False],
        "focus": ["vector", [0.0, 0.0]],
    }
)

# Layers in mod_geometry

layers["circle"] = default_composite.copy()
layers["circle"].update(
    {
        "color": ["color", [0, 0, 0, 1]],
        "radius": ["real", 1.0],
        "feather": ["real", 0.0],
        "origin": ["vector", [0.0, 0.0]],
        "invert": ["bool", False],
    }
)

layers["rectangle"] = default_composite.copy()
layers["rectangle"].update(
    {
        "color": ["color", [0, 0, 0, 1]],
        "point1": ["vector", [0, 0]],
        "point2": ["vector", [1, 1]],
        "expand": ["real", 0.0],
        "invert": ["bool", False],
    }
)

default_shape = default_composite.copy()
default_shape.update(
    {
        "color": ["color", [0, 0, 0, 1]],
        "origin": ["vector", [0.0, 0.0]],
        "invert": ["bool", False],
        "antialias": ["bool", True],
        "feather": ["real", 0.0],
        "blurtype": ["integer", 1],
        "winding_style": ["integer", 0],
    }
)

layers["region"] = default_shape.copy()
layers["region"].update({"bline": ["bline", None]})

layers["outline"] = default_shape.copy()
layers["outline"].update(
    {
        "bline": ["bline", None],
        "round_tip[0]": ["bool", True],
        "round_tip[1]": ["bool", True],
        "sharp_cusps": ["bool", True],
        "width": ["real", 1.0],
        "loopyness": ["real", 1.0],
        "expand": ["real", 0.0],
        "homogeneous_width": ["bool", True],
    }
)

# Layers in mod_gradient

layers["linear_gradient"] = default_composite.copy()
layers["linear_gradient"].update(
    {
        "p1": ["vector", [0, 0]],
        "p2": ["vector", [1, 1]],
        "gradient": ["gradient", {0.0: [0, 0, 0, 1], 1.0: [1, 1, 1, 1]}],
        "loop": ["bool", False],
        "zigzag": ["bool", False],
    }
)

layers["radial_gradient"] = default_composite.copy()
layers["radial_gradient"].update(
    {
        "gradient": ["gradient", {0.0: [0, 0, 0, 1], 1.0: [1, 1, 1, 1]}],
        "center": ["vector", [0, 0]],
        "radius": ["real", 1.0],
        "loop": ["bool", False],
        "zigzag": ["bool", False],
    }
)

# Layers in lyr_std

layers["import"] = default_composite.copy()
layers["import"].update(
    {
        "tl": ["vector", [-1, 1]],
        "br": ["vector", [1, -1]],
        "c": ["integer", 1],
        "gamma_adjust": ["real", 1.0],
        "filename": ["string", ""],  # <string>foo</string>
        "time_offset": ["time", "0s"],
    }
)

# transforms are not blending
layers["warp"] = {
    "src_tl": ["vector", [-1, 1]],
    "src_br": ["vector", [1, -1]],
    "dest_tl": ["vector", [-1, 1]],
    "dest_tr": ["vector", [1, 1]],
    "dest_br": ["vector", [1, -1]],
    "dest_bl": ["vector", [-1, -1]],
    "clip": ["bool", False],
    "horizon": ["real", 4.0],
}

layers["rotate"] = {
    "origin": ["vector", [0.0, 0.0]],
    "amount": ["angle", 0],  # <angle value=.../>
}

layers["translate"] = {"origin": ["vector", [0.0, 0.0]]}

# Layers in mod_filter
layers["blur"] = default_composite.copy()
layers["blur"].update(
    {
        "size": ["vector", [1, 1]],
        "type": ["integer", 3],  # 1 is fast gaussian, 3 is regular
    }
)

# ##### Layer versions #####################################
layer_versions = {
    "outline": "0.2",
    "rectangle": "0.2",
    "linear_gradient": "0.0",
    "blur": "0.2",
    None: "0.1",  # default
}

# ##### Blend Methods ######################################
blend_method_names = {
    0: "composite",
    1: "straight",
    13: "onto",
    21: "straight onto",
    12: "behind",
    16: "screen",
    20: "overlay",
    17: "hand light",
    6: "multiply",
    7: "divide",
    4: "add",
    5: "subtract",
    18: "difference",
    2: "brighten",
    3: "darken",
    8: "color",
    9: "hue",
    10: "saturation",
    11: "luminance",
    14: "alpha brighten",  # deprecated
    15: "alpha darken",  # deprecated
    19: "alpha over",  # deprecated
}

blend_methods = dict((v, k) for (k, v) in blend_method_names.items())


# ##### Functions ##########################################
def paramType(layer, param, value=None):
    if layer in layers.keys():
        layer_params = layers[layer]
        if param in layer_params.keys():
            return layer_params[param][0]
        else:
            raise Exception("Invalid parameter type for layer")
    else:
        # Unknown layer, try to determine parameter type based on value
        if value is None:
            raise Exception("No information for given layer")
        if type(value) == int:
            return "integer"
        elif type(value) == float:
            return "real"
        elif type(value) == bool:
            return "bool"
        elif type(value) == dict:
            if "points" in value.keys():
                return "bline"
            elif 0.0 in value.keys():
                return "gradient"
            else:
                raise Exception("Could not automatically determine parameter type")
        elif type(value) == list:
            if len(value) == 2:
                return "vector"
            elif len(value) == 3 or len(value) == 4:
                return "color"
            else:
                # The first two could also be canvases
                return "canvas"
        elif type(value) == str:
            return "string"


def defaultLayerVersion(layer):
    if layer in layer_versions.keys():
        return layer_versions[layer]
    else:
        return layer_versions[None]


def defaultLayerParams(layer):
    if layer in layers.keys():
        return layers[layer].copy()
    else:
        return {}
