/*
 * Copyright(c) Live2D Inc. All rights reserved.
 *
 * Use of this source code is governed by the Live2D Open Software license
 * that can be found at http://live2d.com/eula/live2d-open-software-license-agreement_en.html.
 */

#pragma once

#include <CubismFramework.hpp>
#include <Math/CubismMatrix44.hpp>
#include <Math/CubismViewMatrix.hpp>
#include "2d/CCSprite.h"
#include "cocos2d.h"
#include "LAppModel.hpp"
#include <vector>

class LAppView : public cocos2d::Node {
public:
    LAppView();

    ~LAppView();

    virtual void onEnter();

    virtual void onExit();

    virtual void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags);

    void onDraw(const cocos2d::Mat4 &transform, uint32_t flags);

    float transformViewX(float deviceX);

    float transformViewY(float deviceY);

    float transformScreenX(float deviceX);

    float transformScreenY(float deviceY);

    void setDebugRectsNode(cocos2d::DrawNode *debugRects);

    void drawDebugRects() const;

    bool setModel(std::string dir, std::string fileName);

    void setPosition(float dx, float dy);

    void setScale(float sx, float sy);

    void touchBegan(const cocos2d::Vec2 &pt);

    void touchMoved(const cocos2d::Vec2 &pt);

    void touchEnded(const cocos2d::Vec2 &pt);

    /**
     * @brief   引数で指定したモーションの再生を開始する。
     *
     * @param[in]   group           モーショングループ名
     * @param[in]   no              グループ内の番号
     * @param[in]   priority        優先度
     * @return                      開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」
     */
    void StartMotion(const char *group, int no, int priority);

    /**
     * @brief   ランダムに選ばれたモーションの再生を開始する。
     *
     * @param[in]   group           モーショングループ名
     * @param[in]   priority        優先度
     * @return                      開始したモーションの識別番号を返す。個別のモーションが終了したか否かを判定するIsFinished()の引数で使用する。開始できない時は「-1」
     */
    void StartRandomMotion(const char *group, int priority);

    /**
     * @brief   引数で指定した表情モーションをセットする
     *
     * @param   expressionID    表情モーションのID
     */
    void SetExpression(const char *expressionID);

    /**
     * @brief   ランダムに選ばれた表情モーションをセットする
     *
     */
    void SetRandomExpression();

    /**
     * @brief キャンバスの幅の取得
     *
     * キャンバスの幅を取得する。
     *
     * @return キャンバスの幅
     */
    float GetCanvasWidth() const;

    /**
     * @brief キャンバスの高さの取得
     *
     * キャンバスの高さを取得する。
     *
     * @return キャンバスの高さ
     */
    float GetCanvasHeight() const;

    /**
     * @brief パーツの個数の取得
     *
     * パーツの個数を取得する。
     *
     * @return パーツの個数
     */
    int GetPartCount() const;

    /**
     * @brief パーツの不透明度の設定
     *
     * パーツの不透明度を設定する。
     *
     * @param[in]   partIndex   パーツのインデックス
     * @param[in]   opacity     パーツの不透明度
     */
    void SetPartOpacity(int partIndex, float opacity);

    /**
     * @brief パーツの不透明度の取得
     *
     * パーツの不透明度を取得する。
     *
     * @param[in]   partIndex   パーツのインデックス
     * @return  パーツの不透明度
     */
    float GetPartOpacity(int partIndex);

    /**
     * @brief パラメータの個数の取得
     *
     * パラメータの個数を取得する。
     *
     * @return パラメータの個数
     */
    int GetParameterCount() const;

    /**
     * @brief パラメータの最大値の取得
     *
     * パラメータの最大値を取得する。
     *
     * @param[in]   parameterIndex  パラメータのインデックス
     * @return パラメータの最大値
     */
    float GetParameterMaximumValue(unsigned int parameterIndex) const;

    /**
     * @brief パラメータの最小値の取得
     *
     * パラメータの最小値を取得する。
     *
     * @param[in]   parameterIndex  パラメータのインデックス
     * @return パラメータの最小値
     */
    float GetParameterMinimumValue(unsigned int parameterIndex) const;

    /**
     * @brief パラメータのデフォルト値の取得
     *
     * パラメータのデフォルト値を取得する。
     *
     * @param[in]   parameterIndex  パラメータのインデックス
     * @return  パラメータのデフォルト値
     */
    float GetParameterDefaultValue(unsigned int parameterIndex) const;

    /**
     * @brief パラメータの値の取得
     *
     * パラメータの値を取得する。
     *
     * @param[in]   parameterIndex  パラメータのインデックス
     * @return  パラメータの値
     */
    float GetParameterValue(int parameterIndex);

    /**
     * @brief パラメータの値の設定
     *
     * パラメータの値を設定する。
     *
     * @param[in]   parameterIndex  パラメータのインデックス
     * @param[in]   value           パラメータの値
     * @param[in]   weight          重み
     */
    void SetParameterValue(int parameterIndex, float value, float weight = 1.0f);

    /**
     * @brief パラメータの値の加算
     *
     * パラメータの値を加算する。
     *
     * @param[in]   parameterIndex  パラメータのインデックス
     * @param[in]   value           加算する値
     * @param[in]   weight          重み
     */
    void AddParameterValue(int parameterIndex, float value, float weight = 1.0f);

    /**
    * @brief パラメータの値の乗算
    *
    * パラメータの値を乗算する。
    *
    * @param[in]   parameterIndex  パラメータのインデックス
    * @param[in]   value           乗算する値
    * @param[in]   weight          重み
    */
    void MultiplyParameterValue(int parameterIndex, float value, float weight = 1.0f);

private:
    Csm::CubismMatrix44 *deviceToScreen;
    Csm::CubismViewMatrix *viewMatrix;
    cocos2d::DrawNode *_debugRects;

    LAppModel *_model;

protected:
    cocos2d::CustomCommand _customCommand;
};
