/*
 * 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 "Model/CubismModel.hpp"
#include "Utils/CubismJson.hpp"

namespace Live2D { namespace Cubism { namespace Framework {
/**
 * @brief パーツの不透明度の設定
 *
 * パーツの不透明度の管理と設定を行う。
 */
class CubismPose
{
public:
    /**
    * @brief パーツにまつわるデータを管理
    *
    * パーツにまつわる諸々のデータを管理する。
    */
    struct PartData
    {
        /**
        * @brief コンストラクタ
        *
        * コンストラクタ。
        */
        PartData();

        /**
        * @brief コピーコンストラクタ
        *
        * コピーコンストラクタ。
        */
        PartData(const PartData& v);

        /**
        * @brief デストラクタ
        *
        * デストラクタ。
        */
        virtual ~PartData();

        /**
        * @brief 代入のオーバーロード
        *
        * 代入のオーバーロード。
        */
        PartData&   operator=(const PartData& v);

        /**
        * @brief 初期化
        *
        * 初期化する。
        *
        * @param[in]   model   初期化に使用するモデル
        */
        void                Initialize(CubismModel* model);

        CubismIdHandle                     PartId;                 ///< パーツID
        csmInt32                            ParameterIndex;         ///< パラメータのインデックス
        csmInt32                            PartIndex;              ///< パーツのインデックス
        csmVector<PartData>                 Link;                   ///< 連動するパラメータ
    };

    /**
     * @brief インスタンスの作成
     *
     * インスタンスを作成する。
     *
     * @param[in]   pose3json    pose3.jsonのデータ
     * @param[in]   size         pose3.jsonのデータのサイズ[Byte]
     * @return                   作成されたインスタンス
     */
    static CubismPose*  Create(const csmByte* pose3json, csmSizeInt size);

    /**
     * @brief インスタンスの破棄
     * 
     * インスタンスを破棄する。
     * 
     * @param[in]   pose    対象のCubismPose
     */
    static void         Delete(CubismPose* pose);

    /**
     * @brief モデルのパラメータの更新
     *
     * モデルのパラメータを更新する。
     *
     * @param[in]   model              対象のモデル
     * @param[in]   deltaTimeSeconds   デルタ時間[秒]
     */
    void                UpdateParameters(CubismModel* model, csmFloat32 deltaTimeSeconds);

private:
    /**
    * @brief コンストラクタ
    *
    * コンストラクタ。
    */
    CubismPose();

    /**
    * @brief デストラクタ
    *
    * デストラクタ。
    */
    virtual ~CubismPose();

    /**
     * @brief 表示を初期化
     *
     * 表示を初期化する。
     *
     * @param[in]   model   対象のモデル
     *
     * @note 不透明度の初期値が0でないパラメータは、不透明度を1に設定する。
     */
    void                Reset(CubismModel* model);

    /**
     * @brief パーツの不透明度をコピー
     *
     * パーツの不透明度をコピーし、リンクしているパーツへ設定する。
     *
     * @param[in]   model   対象のモデル
     */
    void                CopyPartOpacities(CubismModel* model);

    /**
     * @brief パーツのフェード操作を実行
     *
     * パーツのフェード操作を行う。
     *
     * @param[in]   model               対象のモデル
     * @param[in]   deltaTimeSeconds    デルタ時間[秒]
     * @param[in]   beginIndex          フェード操作を行うパーツグループの先頭インデックス
     * @param[in]   partGroupCount      フェード操作を行うパーツグループの個数
     */
    void                DoFade(CubismModel* model, csmFloat32 deltaTimeSeconds, csmInt32 beginIndex, csmInt32 partGroupCount);

    csmVector<PartData>             _partGroups;                ///< パーツグループ
    csmVector<csmInt32>             _partGroupCounts;           ///< それぞれのパーツグループの個数
    csmFloat32                      _fadeTimeSeconds;           ///< フェード時間[秒]
    CubismModel*                    _lastModel;                 ///< 前回操作したモデル
};

}}}
