/*
 * 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.h"

#ifndef NULL
#   define  NULL  0
#endif

namespace Live2D { namespace Cubism { namespace Framework {

/**
 * @brief 2次元ベクトル型
 * 
 * 2次元ベクトル型の機能を提供する。
 */
struct CubismVector2
{
    csmFloat32 X;           ///< X軸の値
    csmFloat32 Y;           ///< Y軸の値

    /**
     * @brief コンストラクタ
     * 
     * コンストラクタ。
     */
    CubismVector2(): X(0.0f), Y(0.0f)
    {}

    /**
     * @brief デストラクタ
     * 
     * デストラクタ。
     */
    CubismVector2(csmFloat32 x, csmFloat32 y) : X(x), Y(y)
    {}

    /**
     * @brief ベクトルの加算
     * 
     * ベクトルを加算する。
     * a + b = result
     * 
     * @param[in]   a   値a
     * @oaram[in]   b   値b
     * @return  a + bの結果
     */
    friend CubismVector2 operator+(const CubismVector2& a, const CubismVector2& b);

    /**
     * @brief ベクトルの減算
     * 
     * ベクトルを減算する。
     * a - b = result
     * 
     * @param[in]   a   値a
     * @param[in]   b   値b
     * @return  a - bの結果
     */
    friend CubismVector2 operator-(const CubismVector2& a, const CubismVector2& b);

    /**
     * @brief ベクトルの乗算（ベクトル値とスカラー値）
     * 
     * ベクトルを乗算する。（ベクトル値とスカラー値）
     * vector * scalar = result
     * 
     * @param[in]   vector  値vector（ベクトル値）
     * @param[in]   scalar  値scalar（スカラー値）
     * @return  vector * scalarの結果（ベクトル値）
     */
    friend CubismVector2 operator*(const CubismVector2& vector, const csmFloat32 scalar);

    /**
     * @brief ベクトルの乗算（スカラー値とベクトル値）
     * 
     * ベクトルを乗算する。（スカラー値とベクトル値）
     * scalar * vector = result
     * 
     * @param[in]   scalar  値scalar（スカラー値）
     * @param[in]   vector  値vector（ベクトル値）
     * @return  scalar * vectorの結果（ベクトル値）
     */
    friend CubismVector2 operator*(const csmFloat32 scalar, const CubismVector2& vector);

    /**
     * @brief ベクトルの除算（ベクトル値とスカラー値）
     * 
     * ベクトルを除算する。（ベクトル値とスカラー値）
     * vector / scalar = result
     * 
     * @param[in]   vector  値vector（ベクトル値）
     * @param[in]   scalar  値scalar（スカラー値）
     * @return  vector / scalarの結果（ベクトル値）
     */
    friend CubismVector2 operator/(const CubismVector2& vector, const csmFloat32 scalar);

    /**
     * @brief 加算
     * 
     * 加算する。
     * 
     * @param[in]   rhs     加算する値
     * @return  結果
     */
    const CubismVector2& operator+=(const CubismVector2& rhs);

    /**
    * @brief 減算
    *
    * 減算する。
    *
    * @param[in]   rhs     減算する値
    * @return  結果
    */
    const CubismVector2& operator-=(const CubismVector2& rhs);

    /**
    * @brief 乗算（ベクトル値）
    *
    * 乗算する。（ベクトル値）
    *
    * @param[in]   rhs     乗算する値（ベクトル値）
    * @return  結果
    */
    const CubismVector2& operator*=(const CubismVector2& rhs);

    /**
    * @brief 除算（ベクトル値）
    *
    * 除算する。（ベクトル値）
    *
    * @param[in]   rhs     除算する値（ベクトル値）
    * @return  結果
    */
    const CubismVector2& operator/=(const CubismVector2& rhs);

    /**
    * @brief 乗算（スカラー値）
    *
    * 乗算する。（スカラー値）
    *
    * @param[in]   scalar     乗算する値（スカラー値）
    * @return  結果
    */
    const CubismVector2& operator*=(const csmFloat32 scalar);

    /**
    * @brief 除算（スカラー値）
    *
    * 除算する。（スカラー値）
    *
    * @param[in]   scalar     除算する値（スカラー値）
    * @return  結果
    */
    const CubismVector2& operator/=(const csmFloat32 scalar);

    /**
     * @brief 等しさの確認（等しいか？）
     * 
     * 値が等しいか？
     * 
     * @param[in]   rhs     確認する値
     * @retval  true    値は等しい
     * @retval  false   値は等しくない
     */
    csmBool operator==(const CubismVector2& rhs) const;

    /**
     * @brief 等しさの確認（等しくないか？）
     * 
     * 値が等しくないか？
     * 
     * @param[in]   rhs     確認する値
     * @retval  true    値は等しくない
     * @retval  false   値は等しい
     */
    csmBool operator!=(const CubismVector2& rhs) const;

    /**
     * @brief 正規化の適用
     * 
     * 正規化する。
     */
    void Normalize();

    /**
     * @brief ベクトルの長さの取得
     * 
     * ベクトルの長さを取得する。
     * 
     * @return  ベクトルの長さ
     */
    csmFloat32 GetLength() const;

    /**
     * @brief ベクトルの距離の取得
     * 
     * ベクトルの距離を取得する。
     * 
     * @param[in]   a   点
     * @return ベクトルの距離
     */
    csmFloat32 GetDistanceWith(CubismVector2 a) const;

    /**
     * @brief ドット積の計算
     * 
     * ドット積を計算する。
     * 
     * @param[in]   a   値
     * @return 結果
     */
    csmFloat32 Dot(const CubismVector2& a) const;
};

// Utility functions for csmVector2.
CubismVector2 operator+(const CubismVector2& a, const CubismVector2& b);
CubismVector2 operator-(const CubismVector2& a, const CubismVector2& b);
CubismVector2 operator*(const CubismVector2& vector, const csmFloat32 scalar);
CubismVector2 operator*(const csmFloat32 scalar, const CubismVector2& vector);
CubismVector2 operator/(const CubismVector2& vector, const csmFloat32 scalar);

}}}

//------------------------- LIVE2D NAMESPACE ------------
