//=============================================================================
// EnemyGraphicReplacement.js
//=============================================================================

/*:ja
 * @target MZ
 * @plugindesc 戦闘中に敵グラフィックを画像で完全に置き換えます
 * @author えむうん
 *
 * @param Picture IDs
 * @text 画像ID
 * @desc 敵グラフィックを置き換える画像ID（カンマ区切り）
 * @default 1,2,3
 *
 * @help
 * このプラグインは戦闘中に敵グラフィックを画像で置き換えます。
 *
 * 使用方法：
 * 1. プラグインパラメータで画像IDを設定します。
 * 2. 戦闘中に「画像の表示」イベントコマンドを使用して、
 *    指定したIDの画像を表示します。
 * 3. 表示された画像が対応する敵グラフィックを完全に置き換えます。
 *
 * 注意：
 * - 画像IDは敵の位置と1対1で対応します。
 * - このプラグインは戦闘中のみ機能します。
 */

(() => {
    const pluginName = "EnemyGraphicReplacement";
    const parameters = PluginManager.parameters(pluginName);
    const pictureIds = parameters['Picture IDs'].split(',').map(Number);

    //-----------------------------------------------------------------------------
    // Game_Screen
    //

    const _Game_Screen_showPicture = Game_Screen.prototype.showPicture;
    Game_Screen.prototype.showPicture = function(pictureId, name, origin, x, y, scaleX, scaleY, opacity, blendMode) {
        _Game_Screen_showPicture.call(this, pictureId, name, origin, x, y, scaleX, scaleY, opacity, blendMode);
        if ($gameParty.inBattle() && pictureIds.includes(pictureId)) {
            const enemyIndex = pictureIds.indexOf(pictureId);
            const enemy = $gameTroop.members()[enemyIndex];
            if (enemy) {
                enemy.setGraphicFromPicture(pictureId);
                if (SceneManager._scene instanceof Scene_Battle) {
                    SceneManager._scene._spriteset.replaceEnemySprite(enemyIndex);
                }
            }
        }
    };

    //-----------------------------------------------------------------------------
    // Game_Enemy
    //

    Game_Enemy.prototype.setGraphicFromPicture = function(pictureId) {
        this._replacedGraphicPictureId = pictureId;
    };

    const _Game_Enemy_performCollapse = Game_Enemy.prototype.performCollapse;
    Game_Enemy.prototype.performCollapse = function() {
        _Game_Enemy_performCollapse.call(this);
        if (this._replacedGraphicPictureId) {
            const picture = $gameScreen.picture(this._replacedGraphicPictureId);
            if (picture) {
                picture._opacity = 0;
            }
        }
    };

    //-----------------------------------------------------------------------------
    // Spriteset_Battle
    //

    const _Spriteset_Battle_createEnemies = Spriteset_Battle.prototype.createEnemies;
    Spriteset_Battle.prototype.createEnemies = function() {
        _Spriteset_Battle_createEnemies.call(this);
        this._enemyPictureSprites = [];
    };

    Spriteset_Battle.prototype.replaceEnemySprite = function(index) {
        const enemy = $gameTroop.members()[index];
        if (enemy && enemy._replacedGraphicPictureId) {
            const oldSprite = this._enemySprites[index];
            const newSprite = new Sprite_EnemyPicture(enemy);
            this._enemySprites[index] = newSprite;
            this._battleField.addChild(newSprite);
            this._battleField.removeChild(oldSprite);
        }
    };

    //-----------------------------------------------------------------------------
    // Sprite_EnemyPicture
    //

    function Sprite_EnemyPicture() {
        this.initialize(...arguments);
    }

    Sprite_EnemyPicture.prototype = Object.create(Sprite_Enemy.prototype);
    Sprite_EnemyPicture.prototype.constructor = Sprite_EnemyPicture;

    Sprite_EnemyPicture.prototype.initialize = function(enemy) {
        Sprite_Enemy.prototype.initialize.call(this, enemy);
        this._pictureSprite = new Sprite();
        this.addChild(this._pictureSprite);
    };

    Sprite_EnemyPicture.prototype.loadBitmap = function() {
        Sprite_Enemy.prototype.loadBitmap.call(this);
        this.bitmap.addLoadListener(this.hideOriginalSprite.bind(this));
    };

    Sprite_EnemyPicture.prototype.hideOriginalSprite = function() {
        this.bitmap.paintOpacity = 0;
    };

    Sprite_EnemyPicture.prototype.updateBitmap = function() {
        Sprite_Enemy.prototype.updateBitmap.call(this);
        this.updatePictureBitmap();
    };

    Sprite_EnemyPicture.prototype.updatePictureBitmap = function() {
        if (this._enemy && this._enemy._replacedGraphicPictureId) {
            const picture = $gameScreen.picture(this._enemy._replacedGraphicPictureId);
            if (picture) {
                const pictureName = picture.name();
                if (this._pictureName !== pictureName) {
                    this._pictureName = pictureName;
                    this._pictureSprite.bitmap = ImageManager.loadPicture(pictureName);
                }
            }
        }
    };

    Sprite_EnemyPicture.prototype.updatePosition = function() {
        Sprite_Enemy.prototype.updatePosition.call(this);
        this.updatePicturePosition();
    };

    Sprite_EnemyPicture.prototype.updatePicturePosition = function() {
        if (this._enemy && this._enemy._replacedGraphicPictureId) {
            const picture = $gameScreen.picture(this._enemy._replacedGraphicPictureId);
            if (picture && this._pictureSprite) {
                this._pictureSprite.x = picture.x() - this.x;
                this._pictureSprite.y = picture.y() - this.y;
                this._pictureSprite.scale.x = picture.scaleX() / 100;
                this._pictureSprite.scale.y = picture.scaleY() / 100;
                this._pictureSprite.opacity = picture.opacity();
                this._pictureSprite.blendMode = picture.blendMode();
            }
        }
    };

    //-----------------------------------------------------------------------------
    // BattleManager
    //

    const _BattleManager_endBattle = BattleManager.endBattle;
    BattleManager.endBattle = function(result) {
        $gameTroop.members().forEach(enemy => {
            if (enemy._replacedGraphicPictureId) {
                $gameScreen.erasePicture(enemy._replacedGraphicPictureId);
                enemy._replacedGraphicPictureId = null;
            }
        });
        _BattleManager_endBattle.call(this, result);
    };

})();