// DarkPlasma_Promise_ShopLayout 1.0.3
// Copyright (c) 2020 DarkPlasma

/**
 * 2021/09/05 1.0.3 二刀流時、盾の表示がおかしい不具合を修正
 * 2020/09/08 1.0.2 rollup構成へ移行
 * 2020/09/05 1.0.1 歩行グラフィックをプリロードするように修正
 * 2020/09/04 1.0.0 初回
 */

/*:ja
 * @plugindesc Promise用ショップレイアウト
 * @author DarkPlasma
 * @license No License
 *
 * @target MZ
 *
 * @help
 * version: 1.0.3
 * ショップのレイアウトをいい感じにします。
 */

(() => {
  'use strict';

  /**
   * 命中率、回避率、会心率、魔法回避率、魔法反射率
   */
  const XPARAM_IDS = [0, 1, 2, 4, 5];

  /**
   * アイテムの追加能力値の合計（％）を返す
   * @param {MZ.Weapon|MZ.Armor} item アイテムデータ
   * @param {number} paramId パラメータID
   * @return {number}
   */
  function itemXParamTraitSum(item, paramId) {
    return item
      ? Math.round(
          item.traits
            .filter((trait) => {
              return trait.code === Game_BattlerBase.TRAIT_XPARAM && trait.dataId === paramId;
            })
            .reduce((a, b) => a + b.value, 0) * 100
        )
      : 0;
  }

  const _Scene_Shop_createStatusWindow = Scene_Shop.prototype.createStatusWindow;
  Scene_Shop.prototype.createStatusWindow = function () {
    _Scene_Shop_createStatusWindow.call(this);
    this._statusWindow.setActor($gameParty.leader());
    this._actorIndex = 0;
  };

  const _Scene_Shop_createBuyWindow = Scene_Shop.prototype.createBuyWindow;
  Scene_Shop.prototype.createBuyWindow = function () {
    _Scene_Shop_createBuyWindow.call(this);
    this._buyWindow.setHandler('pagedown', this.changeToNextActor.bind(this));
    this._buyWindow.setHandler('pageup', this.changeToPreviousActor.bind(this));
  };

  Scene_Shop.prototype.changeToNextActor = function () {
    const selectingItem = this._buyWindow.item();
    if (!DataManager.isWeapon(selectingItem) && !DataManager.isArmor(selectingItem)) {
      return;
    }
    this._actorIndex++;
    if (this._actorIndex >= $gameParty.members().length) {
      this._actorIndex = 0;
    }
    this._statusWindow.setActor($gameParty.members()[this._actorIndex]);
  };

  Scene_Shop.prototype.changeToPreviousActor = function () {
    const selectingItem = this._buyWindow.item();
    if (!DataManager.isWeapon(selectingItem) && !DataManager.isArmor(selectingItem)) {
      return;
    }
    this._actorIndex--;
    if (this._actorIndex < 0) {
      this._actorIndex = $gameParty.members().length - 1;
    }
    this._statusWindow.setActor($gameParty.members()[this._actorIndex]);
  };

  /**
   * ショップ商品リストのページ単位スクロールは左右キーに割り当てる
   */
  const _Window_ShopBuy_cursorPageup = Window_ShopBuy.prototype.cursorPageup;
  const _Window_ShopBuy_cursorPagedown = Window_ShopBuy.prototype.cursorPagedown;

  Window_ShopBuy.prototype.cursorLeft = function () {
    _Window_ShopBuy_cursorPageup.call(this);
  };

  Window_ShopBuy.prototype.cursorRight = function () {
    _Window_ShopBuy_cursorPagedown.call(this);
  };

  /**
   * LRはキャラ切り替え用につぶしておく
   */
  Window_ShopBuy.prototype.cursorPageup = function () {};
  Window_ShopBuy.prototype.cursorPagedown = function () {};

  Window_ShopBuy.prototype.processPageup = function () {
    this.updateInputData();
    this.playCursorSound();
    this.callHandler('pageup');
  };

  Window_ShopBuy.prototype.processPagedown = function () {
    this.updateInputData();
    this.playCursorSound();
    this.callHandler('pagedown');
  };

  const _Window_ShopStatus_initialize = Window_ShopStatus.prototype.initialize;
  Window_ShopStatus.prototype.initialize = function (rect) {
    _Window_ShopStatus_initialize.call(this, rect);
    this._actor = null;
    this.contents.fontSize = this.statusFontSize();
    this.preloadActorGraphic();
  };

  Window_ShopStatus.prototype.preloadActorGraphic = function () {
    $gameParty.members().forEach((actor) => ImageManager.loadCharacter(actor.characterName()));
  };

  Window_ShopStatus.prototype.setActor = function (actor) {
    if (this._actor !== actor) {
      this._actor = actor;
      this.refresh();
    }
  };

  Window_ShopStatus.prototype.drawEquipInfo = function (x, y) {
    if (this._actor) {
      const actorY = y;
      const bitmap = ImageManager.loadCharacter(this._actor.characterName());
      if (!bitmap.isReady()) {
        bitmap.addLoadListener(this.drawEquipInfo.bind(this, x, y));
      }
      this.drawActorEquipInfo(x, actorY, this._actor);
      this.drawActorCharacter(this._actor, 230, 80);
    }
  };

  Window_ShopStatus.prototype.drawActorEquipInfo = function (x, y, actor) {
    const item1 = this.currentEquippedItem(actor, this._item.etypeId);
    const width = this.innerWidth - x - this.itemPadding();
    const slotName = this.currentSlotName(actor, this._item.etypeId);
    const enabled = actor.canEquip(this._item) && slotName;
    this.changePaintOpacity(enabled);
    this.resetTextColor();
    this.drawText(actor.name(), x, y, width);
    if (enabled) {
      this.drawActorParamChange(x, y + this.lineHeight() * 2 + this.itemPadding(), actor, item1);
    }
    this.changeTextColor(ColorManager.systemColor());
    this.drawText(slotName ? slotName : '盾', x, y + this.lineHeight(), width);
    this.drawItemName(item1, this.textWidth('装飾品1 ') + x, y + this.lineHeight(), width);
    this.changePaintOpacity(true);
  };

  Window_ShopStatus.prototype.drawActorParamChange = function (x, y, actor, item1) {
    const width = this.innerWidth / 2 - this.textWidth('00');
    Array.from(Array(8).keys())
      .map((paramId) => {
        return this._item.params[paramId] - (item1 ? item1.params[paramId] : 0);
      })
      .forEach((change, paramId) => {
        this.changeTextColor(ColorManager.systemColor());
        this.drawText(TextManager.param(paramId), x, y + this.statusLineHeight() * paramId, width, 'left');
        this.changeTextColor(ColorManager.paramchangeTextColor(change));
        this.drawText((change > 0 ? '+' : '') + change, x, y + this.statusLineHeight() * paramId, width, 'right');
      });
    const xparamX = this.innerWidth / 2;
    XPARAM_IDS.map((paramId) => {
      return {
        change: itemXParamTraitSum(this._item, paramId) - itemXParamTraitSum(item1, paramId),
        paramId: paramId,
      };
    }).forEach((changeXparam, index) => {
      this.changeTextColor(ColorManager.systemColor());
      this.drawText(
        TextManager.xparam(changeXparam.paramId),
        xparamX,
        y + this.statusLineHeight() * index,
        width,
        'left'
      );
      this.changeTextColor(ColorManager.paramchangeTextColor(changeXparam.change));
      this.drawText(
        (changeXparam.change > 0 ? '+' : '') + changeXparam.change,
        xparamX,
        y + this.statusLineHeight() * index,
        width,
        'right'
      );
    });
  };

  Window_ShopStatus.prototype.currentEquippedItem = function (actor, etypeId) {
    const equips = actor.equips();
    const slots = actor.equipSlots();
    const slotIndex = slots.findIndex((slot) => slot === etypeId) + this._pageIndex;
    return equips[slotIndex];
  };

  Window_ShopStatus.prototype.currentSlotName = function (actor, etypeId) {
    const slots = actor.equipSlots();
    const slotIndex = slots.findIndex((slot) => slot === etypeId) + this._pageIndex;
    return this.actorSlotName(actor, slotIndex);
  };

  Window_ShopStatus.prototype.maxPages = function () {
    if (!this._actor || !this._item) {
      return 1;
    }
    return this.countCurrentSlotType(this._actor, this._item.etypeId);
  };

  /**
   * 対象装備タイプIDのスロットがいくつあるか
   * @param {Game_Actor} actor アクター
   * @param {number} etypeId 装備タイプID
   * @return {number}
   */
  Window_ShopStatus.prototype.countCurrentSlotType = function (actor, etypeId) {
    const slots = actor.equipSlots();
    return slots.filter((slot) => slot === etypeId).length;
  };

  Window_ShopStatus.prototype.statusFontSize = function () {
    return 20;
  };

  Window_ShopStatus.prototype.commandFontSize = function () {
    return 18;
  };

  Window_ShopStatus.prototype.statusLineHeight = function () {
    return this.statusFontSize() + this.statusPadding();
  };

  Window_ShopStatus.prototype.statusPadding = function () {
    return 4;
  };

  Window_ShopStatus.prototype.drawCommand = function () {
    this.contents.fontSize = this.commandFontSize();
    this.changeTextColor(ColorManager.textColor(6));
    if (this._item && (DataManager.isWeapon(this._item) || DataManager.isArmor(this._item))) {
      this.drawText('W: 다음', this.innerWidth - 200, this.innerHeight - 50, 200, 'right');
      this.drawText('Q: 이전', this.innerWidth - 200, this.innerHeight - 30, 200, 'right');
    }
    if (this.maxPages() > 1) {
      this.drawText('Shift: 장비 슬롯', this.innerWidth - 200, this.innerHeight - 70, 200, 'right');
    }
    this.contents.fontSize = this.statusFontSize();
  };

  const _Window_ShopStatus_refresh = Window_ShopStatus.prototype.refresh;
  Window_ShopStatus.prototype.refresh = function () {
    if (this._pageIndex >= this.maxPages()) {
      this._pageIndex = 0;
    }
    _Window_ShopStatus_refresh.call(this);
    this.drawCommand();
  };
})();
