//=============================================================================
// RPG Maker MZ - Sprite_ProgressBar
//
// Copyright 2024 Panzer-IV. All rights reserved.
// This source code or any portion thereof must not be
// reproduced or used without licensed in any manner whatsoever.
//=============================================================================
/*:
 * @target MZ
 * @plugindesc プログレスバー部品
 * @author 四号戦車
 * @base DebugSwitch
 * @base AsyncLoadImage
 * @base Sprite_InputHandle
 * @base SmartAnimation
 * @orderAfter DebugSwitch
 * @orderAfter AsyncLoadImage
 * @orderAfter Sprite_InputHandle
 * @orderAfter SmartAnimation
 *
 * @param comment
 * @text 備考欄
 * @desc プラグイン側では使用しません。
 *       メモ欄としてお使いください。
 * @type multiline_string
 * @default
 *
 * @help Sprite_ProgressBar.js
 *
 * Version: 0.0.1
 *
 * 進捗バーのUIパーツ。
 * これ単体では動作しません。
 *
 * 変数もしくは直に値を指定する事が出来ます。
 */
(() => {
	"use strict";

    //========================================================================
    // プラグイン定義
    //========================================================================
    const pluginName = "Sprite_ProgressBar";
    const script = document.currentScript;
    const param  = PluginManagerEx.createParameter(script);

    //========================================================================
    // 定数定義
    //========================================================================

    //========================================================================
    // クラス定義 (GradientPoint)
    //========================================================================
    class GradientPoint {
        constructor(percent, colorCode, alpha) {
            this._percent = percent;
            this._color = colorCode;
            if (!!alpha || alpha === 0) {
                this._alpha = alpha;
            } else {
                this._alpha = 255;
            }
        }

        get percent() {
            return this._percent;
        }

        get colorCode() {
            return this._color;
        }

        get alpha() {
            return this._alpha;
        }

        getPosition() {
            return this._percent / 100;
        }

        getColor() {
            return PluginUtils.parseRgbaHexToCss(this._color, this._alpha);
        }
    }
    window.GradientPoint = GradientPoint;

    //========================================================================
    // クラス定義 (Sprite_ProgressBar)
    //========================================================================
    class Sprite_ProgressBar extends Sprite {
        constructor(width, height, max) {
            super(new Bitmap(width, height));
            this._max = max;
            this._lineColor = '#FFFFFF';
            this._bgColior = '#000000';
            this._progressColor = '#FF0000';
            this._lineWidth = 6;
            this._progress = 0;
            this._targetProgres = 0;
            this._bondVariable = 0;
            this._isGradient = false;

            this._barSprite = new Sprite(new Bitmap(width, height));
            this.addChild(this._barSprite);

            this.updateFrame();
        }

        set max(value) {
            this._max = value;
            this.paintProgress();
        }

        get max() {
            return this._max;
        }

        set lineColor(value) {
            this._bgColior = value;
            this.paintFrame();
        }

        get lineColor() {
            return this._bgColior;
        }

        set lineWidth(value) {
            this._lineWidth = value;
        }

        get lineWidth() {
            return this._lineWidth;
        }

        getProgress() {
            return this._targetProgres;
        }

        setProgress(value, force) {
            this._targetProgres = Number(value).clamp(0, this._max);
            if (force === true) {
                this._progress = this._targetProgres;
            }
            this.paintProgress();
        }

        bind(variableId) {
            if (variableId > 0) {
                this._bondVariable = variableId;
                this.setProgress(PluginUtils.getVariables(variableId), true);
            }
        }

        setProgressColor(color) {
            this._progressColor = color;
            this._isGradient = false;
            this.paintProgress();
        }

        setProgressGradation(gradationcolors) {
            if (!!gradationcolors && Array.isArray(gradationcolors)) {
                this._progressColor = gradationcolors;
                this._isGradient = true;
                this.paintProgress();
            } else {
                Logger.w(`[Sprite_ProgressBar] argument is not valid: gradationcolors = ${gradationcolors}`);
            }
        }

        _refresh() {
            super._refresh();
            this.updateFrame();
        }

        updateFrame() {
            if (!!this._barSprite) {
                const width = this.width;
                const height = this.height;

                const mergin = (this._lineWidth * 2);
                this._barSprite.bitmap = new Bitmap(width - mergin, height - mergin);
                this._barSprite.move(this._lineWidth, this._lineWidth);
                this._drawProgressBar();
            }
        }

        _drawProgressBar() {
            this.paintFrame();
            this.paintProgress();
        }

        paintFrame() {
            const bitmap = this.bitmap;
            bitmap.clear();
            bitmap.fillAll(this._lineColor);

            const width = this.width - (this._lineWidth * 2);
            const height = this.height - (this._lineWidth * 2);
            bitmap.fillRect(this._lineWidth, this._lineWidth, width, height, this._bgColior);
        }

        paintProgress() {
            const bitmap = this._barSprite.bitmap;
            bitmap.clear();

            const width = this.width - (this._lineWidth * 2);
            const height = this.height - (this._lineWidth * 2);

            if (this._isGradient) {
                const context = bitmap.context;
                const grad = context.createLinearGradient(0, 0, width, 0);

                if (this._progressColor[0].percent > 0) {
                    grad.addColorStop(0, this._progressColor[0].getColor());
                }

                this._progressColor.forEach(gradient => {
                    grad.addColorStop(gradient.getPosition(), gradient.getColor());
                });

                if (this._progressColor[this._progressColor.length - 1].percent < 100) {
                    grad.addColorStop(0, this._progressColor[this._progressColor.length - 1].getColor());
                }

                context.save();
                context.fillStyle = grad;
                context.fillRect(0, 0, width, height);
                context.restore();
                bitmap._baseTexture.update();
            } else {
                bitmap.fillRect(0, 0, width, height);
            }

            const percent = PluginUtils.percent(this._max, this._progress) / 100;
            if (this._progress < this._max) {
                const percentX = width * percent;
                bitmap.clearRect(percentX, 0, width, height);
            }
        }
    }
    window.Sprite_ProgressBar = Sprite_ProgressBar;
})();
