//=============================================================================
// KMS_ShopInventory.js
//   Last update: 2017/02/03
//=============================================================================

/*:
 * @plugindesc
 * [v0.1.0] Add the inventory control function for shops.
 * 
 * @author TOMY (Kamesoft)
 *
 * @param Sold out text
 * @default SOLD OUT
 * @desc "Sold out" text which is displayed instead of item's price.
 *
 * @param Caption for stock
 * @default Stock
 * @desc The caption for stocks of items.
 *
 * @param Stock display
 * @default 1
 * @desc
 *  Specify the window for displaying stock numbers.
 *  0: ShopNumber  1: ShopStatus
 *
 * @help
 *
 * ## Plugin commands
 *   ShopInventory apply shop1          # Use an inventory info specified as ID:shop1 when the event command "Shop" is called in the next
 *   ShopInventory supplySpeed shop1 3  # All items are supplied to ID:shop1 by 3x
 *   ShopInventory supplySpeed shop2 0  # Do not supply any item to ID:shop2
 *   ShopInventory restockAll shop1     # Stock of ID:shop1 is replenished fully
 *   ShopInventory resetAll             # Initialize all inventory info
 */

/*:ja
 * @plugindesc
 * [v0.1.0] アイテムの在庫管理機能を追加します。
 * 
 * @author TOMY (Kamesoft)
 *
 * @param Sold out text
 * @default SOLD OUT
 * @desc 在庫がない場合、アイテムの価格の代わりに表示するテキストです。
 *
 * @param Caption for stock
 * @default 在庫
 * @desc 在庫表示の名称です。
 *
 * @param Stock display
 * @default 1
 * @desc
 *  在庫数を表示するウィンドウを指定します。
 *  0: 購入数選択  1: ステータス
 *
 * @help
 *
 * ■ プラグインコマンド
 *   ShopInventory apply shop1          # 次の「ショップの処理」で ID:shop1 の在庫情報を使用
 *   ShopInventory supplySpeed shop1 3  # ID:shop1 の在庫を 3 倍速で補充
 *   ShopInventory supplySpeed shop2 0  # ID:shop2 の在庫は補充しない
 *   ShopInventory restockAll shop1     # ID:shop1 の在庫を最大まで補充
 *   ShopInventory resetAll             # 在庫情報を初期化
 */

var KMS = KMS || {};

// セーブデータからの復元を可能にするため、セーブデータに入るクラスをグローバルスコープに置く
function Game_ShopInventory()
{
    this.initialize.apply(this, arguments);
}

function Game_ShopSupplySchedule()
{
    this.initialize.apply(this, arguments);
}

function Game_ShopInventorySupplier()
{
    this.initialize.apply(this, arguments);
}

(function() {

'use strict';

var PluginName = 'KMS_ShopInventory';

KMS.imported = KMS.imported || {};
KMS.imported['ShopInventory'] = true;

var pluginParams = PluginManager.parameters(PluginName);
var Params = {};
Params.soldOutText = pluginParams['Sold out text'] || 'SOLD OUT';
Params.stockCaption = pluginParams['Caption for stock'] || 'Stock';
Params.showStockInStatus = Number(pluginParams['Show stock in status'] || 1);


// 商品の補充モード
var SupplyMode =
{
    playtime:    0,     // プレイ時間
    battleCount: 1,     // 戦闘回数

    max: 1
};

    // 商品の補充モードシンボル
var SupplyModeSymbol =
{
    T: SupplyMode.playtime,
    B: SupplyMode.battleCount
};

// 定数
var Const =
{
    debug:             false,           // デバッグモード
    pluginCommandCode: 'ShopInventory'  // プラグインコマンドコード
};

// デバッグログ
var debuglog;
if (Const.debug)
{
    debuglog = function() { console.log(arguments); }
}
else
{
    debuglog = function() { }
}

// トルコロケールで i の小文字変換が期待と異なる件に対する W/A
var toUpper = function(s) { return s.toUpperCase(); };

if ('I' !== 'i'.toUpperCase())
{
    // トルコ用
    toUpper = function(s) { return s.replace(/[A-Z]/g, function(ch) { return String.fromCharCode(ch.charCodeAt(0) & ~32); }); };
}

var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args)
{
    _Game_Interpreter_pluginCommand.call(this, command, args);

    if (command !== Const.pluginCommandCode)
    {
        return;
    }

    // TODO: 商品の個別補充

    switch (args[0])
    {
    case 'apply':       // 在庫情報の呼び出し (inventoryId)
        if (args[1] == null)
        {
            console.error('[%1 %2] Inventory ID is not specified.'.format(Const.pluginCommandCode, args[0]));
        }
        else
        {
            $gameTemp.nextInventoryId = args[1];
        }
        break;

    case 'supplySpeed': // 補充速度の変更 (inventoryId speed)
        if (isNaN(args[2]))
        {
            console.error('[%1 %2] Invalid speed (%3).'.format(Const.pluginCommandCode, args[0], args[2]));
        }
        else
        {
            // インベントリ未作成の場合は自動的に作成される
            var speed = Number(args[2]);
            $gameSystem.getInventoryById(args[1]).setSupplySpeed();
        }
        break;

    case 'restockAll':     // 在庫の完全補充 (inventoryId)
        if ($gameSystem.existsInventory(args[1]))
        {
            $gameSystem.getInventoryById(args[1]).initializeStock();
        }
        else
        {
            console.log('[%1 %2] Inventory "%3" is not exist.'.format(Const.pluginCommandCode, args[0], args[1]));
        }
        break;

    case 'resetAll':    // 全ショップの在庫情報初期化
        $gameSystem.clearInventories();
        break;

    default:
        // 不明なコマンド
        console.error('[%1 %2] Unknown command.'.format(Const.pluginCommandCode, args[0]));
        break;
    }
}


//-----------------------------------------------------------------------------
// Item

/**
 * 同一のアイテムであるか
 */
function isSameItem(item1, item2)
{
    if (item1.id !== item2.id)
    {
        return false;
    }


    var result =
        (DataManager.isItem(item1) && DataManager.isItem(item2)) ||
        (DataManager.isWeapon(item1) && DataManager.isWeapon(item2)) ||
        (DataManager.isArmor(item1) && DataManager.isArmor(item2));

    if (KMS.imported['AbilityOrb'])
    {
        result |= DataManager.isAbilityOrb(item1) && DataManager.isAbilityOrb(item2);
    }

    return result;
}

/**
 * 在庫メモの解析
 */
function parseNotesForStock(item)
{
    var note = item.meta['kms_shop_stock'];
    if (note == null)
    {
        return;
    }

    var opts = note.replace(/\s+/g, '').split(/,/);
    if (!opts || opts.length < 2)
    {
        return;
    }

    if (isNaN(opts[0]))
    {
        console.error('%1: Invalid stock count'.format(item.name));
        return;
    }

    if (isNaN(opts[1]))
    {
        console.error('%1: Invalid supply interval'.format(item.name));
        return;
    }

    item.shopStockCountMax       = parseInt(opts[0]);
    item.shopStockSupplyInterval = parseInt(opts[1]);

    if (opts.length >= 3)
    {
        // 補充モードの判定 (不正なモードの場合はプレイ時間にフォールバック)
        var modeSymbol = toUpper(opts[2] || 'T');
        if (SupplyModeSymbol[modeSymbol] != null)
        {
            item.shopStockSupplyMode = SupplyModeSymbol[modeSymbol];
        }
        else
        {
            console.error('%1: Invalid supply mode'.format(item.name));
            item.shopStockSupplyMode = SupplyMode.playtime;
        }
    }
    else
    {
        // モード省略時はプレイ時間扱い
        item.shopStockSupplyMode = SupplyMode.playtime;
    }

    debuglog('%1: Max=%2, Interval=%3, Mode=%4'.format(
        item.name,
        item.shopStockCountMax,
        item.shopStockSupplyInterval,
        item.shopStockSupplyMode));
}

/**
 * 在庫上限の取得
 */
function getStockMax(item)
{
    return item.shopStockCountMax;
}

/**
 * 補充間隔の取得
 */
function getSupplyInterval(item)
{
    return item.shopStockSupplyInterval;
}

/**
 * 補充モードの取得
 */
function getSupplyMode(item)
{
    return item.shopStockSupplyMode;
}


//-----------------------------------------------------------------------------
// DataManager

var _DataManager_onLoad = DataManager.onLoad;
DataManager.onLoad = function(object)
{
    _DataManager_onLoad.call(this, object);

    // 在庫設定の解析
    if (object === $dataItems ||
        object === $dataWeapons ||
        object === $dataArmors ||
        (KMS.imported['AbilityOrb'] && object === $dataKmsAbilityOrbs))
    {
        for (var i = 0; i < object.length; i++)
        {
            var obj = object[i];
            if (obj != null)
            {
                parseNotesForStock(obj);
            }
        }
    }
};


//-----------------------------------------------------------------------------
// Game_Temp

/**
 * 次回呼び出す在庫管理情報の ID
 *
 * @property nextInventoryId
 * @type String
 */
Object.defineProperty(Game_Temp.prototype, 'nextInventoryId', {
    get: function()
    {
        return this._nextInventoryId;
    },
    set: function(value)
    {
        this._nextInventoryId = value;
    },
    configurable: true
});

var _Game_Temp_initialize = Game_Temp.prototype.initialize;
Game_Temp.prototype.initialize = function()
{
    _Game_Temp_initialize.call(this);

    this._nextInventoryId = null;
};


//-----------------------------------------------------------------------------
// Game_System

var _Game_System_initialize = Game_System.prototype.initialize;
Game_System.prototype.initialize = function()
{
    _Game_System_initialize.call(this);

    this.clearInventories();
};

/**
 * 指定 ID に対応する店舗在庫が存在するか
 */
Game_System.prototype.existsInventory = function(id)
{
    this._inventories = this._inventories || {};
    return this._inventories[id] != null;
};

/**
 * 指定 ID に対応する店舗在庫を取得
 */
Game_System.prototype.getInventoryById = function(id)
{
    if (!this.existsInventory(id))
    {
        this._inventories[id] = new Game_ShopInventory(id);
    }

    return this._inventories[id];
};

/**
 * 店舗在庫の全クリア
 */
Game_System.prototype.clearInventories = function()
{
    this._inventories = {};
    this._inventorySupplier = new Game_ShopInventorySupplier();
};

/**
 * 在庫補充スケジュールの登録
 */
Game_System.prototype.registerInventorySupplySchedule = function(inventoryId, item)
{
    if (!this._inventorySupplier)
    {
        this._inventorySupplier = new Game_ShopInventorySupplier();
    }

    var schedule = new Game_ShopSupplySchedule(inventoryId, item);
    this._inventorySupplier.register(schedule);
};

/**
 * 在庫補充スケジュールの更新
 */
Game_System.prototype.updateInventorySupplier = function()
{
    if (!this._inventorySupplier)
    {
        this._inventorySupplier = new Game_ShopInventorySupplier();
    }

    this._inventorySupplier.update();
};


//-----------------------------------------------------------------------------
// Game_ShopInventory
//
// 店舗の在庫を管理するクラス

Object.defineProperties(Game_ShopInventory.prototype, {
    id: { get: function() { return this._id; }, configurable: true },
    supplySpeed: { get: function() { return this._supplySpeed; }, configurable: true }
});

Game_ShopInventory.prototype.initialize = function(id)
{
    this._id = id;
    this._supplySpeed = 1;

    this.initializeStock();
};

/**
 * コンテナの初期化
 */
Game_ShopInventory.prototype.initializeStock = function(item)
{
    this._itemStock   = {};
    this._weaponStock = {};
    this._armorStock  = {};

    this._abilityOrbStock = {};
};

/**
 * 商品のコンテナを取得
 */
Game_ShopInventory.prototype.itemContainer = function(item)
{
    if (!item)
    {
        return null;
    }
    else if (DataManager.isItem(item))
    {
        return this._itemStock;
    }
    else if (DataManager.isWeapon(item))
    {
        return this._weaponStock;
    }
    else if (DataManager.isArmor(item))
    {
        return this._armorStock;
    }
    else if (KMS.imported['AbilityOrb'] && DataManager.isAbilityOrb(item))
    {
        return this._abilityOrbStock;
    }
    else
    {
        console.error('Game_ShopInventory: Invalid item type');
        return null;
    }
};

/**
 * 商品の補充速度を設定
 */
Game_ShopInventory.prototype.setSupplySpeed = function(speed)
{
    this._supplySpeed = Math.max(speed, 0);
};

/**
 * 商品の補充間隔を取得
 */
Game_ShopInventory.prototype.getSupplyInterval = function(item)
{
    return Math.max(Math.floor(getSupplyInterval(item) * this._supplySpeed), 0);
};

/**
 * 商品の在庫数を取得
 */
Game_ShopInventory.prototype.getStock = function(item)
{
    if (!this.isStockManaged(item))
    {
        // 在庫管理外なら常に MAX 扱い
        return $gameParty.maxItems(item);
    }

    var stock = this.itemContainer(item);
    if (stock[item.id] == null)
    {
        // 初回参照時は在庫をフルにする
        stock[item.id] = this.getStockMax(item);
    }

    return stock[item.id];
};

/**
 * 商品の在庫数を設定
 */
Game_ShopInventory.prototype.setStock = function(item, number)
{
    if (!this.isStockManaged(item))
    {
        return;
    }

    var stock = this.itemContainer(item);
    if (stock != null)
    {
        stock[item.id] = number.clamp(0, this.getStockMax(item));
    }
};

/**
 * 商品が在庫管理対象か
 */
Game_ShopInventory.prototype.isStockManaged = function(item)
{
    return getStockMax(item) != null;
};

/**
 * 商品の在庫数上限を取得
 */
Game_ShopInventory.prototype.getStockMax = function(item)
{
    // TODO: 店ごとに上限を指定できるようにしたい
    return this.isStockManaged(item) ? getStockMax(item) : $gameParty.maxItems(item);
};

/**
 * 商品の在庫数が上限か
 */
Game_ShopInventory.prototype.isStockFull = function(item)
{
    return this.getStock(item) >= this.getStockMax(item);
};

/**
 * 商品の在庫数があるか
 */
Game_ShopInventory.prototype.isStockAvailable = function(item)
{
    return this.getStock(item) > 0;
};

/**
 * 商品の在庫数を増やす
 */
Game_ShopInventory.prototype.gainStock = function(item, amount)
{
    var prevStock = this.getStock(item);
    this.setStock(item, prevStock + amount);
    return this.getStock(item) - prevStock;
};

/**
 * 商品の在庫数を減らす
 */
Game_ShopInventory.prototype.loseStock = function(item, amount)
{
    return -this.gainStock(item, -amount);
};


//-----------------------------------------------------------------------------
// Game_ShopSupplySchedule
//
// 店舗の在庫補充タイミングを制御するクラス

Object.defineProperties(Game_ShopSupplySchedule.prototype, {
    inventoryId: { get: function() { return this._inventoryId; },   configurable: true },
    item:        { get: function() { return this._item.object(); }, configurable: true }
});

Game_ShopSupplySchedule.prototype.initialize = function(inventoryId, item)
{
    this._inventoryId = inventoryId;
    this._item        = new Game_Item(item);
    this._startCount  = -1;
};

/**
 * 補充間隔の取得
 */
Game_ShopSupplySchedule.prototype.getSupplyInterval = function()
{
    var inventory = $gameSystem.getInventoryById(this.inventoryId);
    return inventory.getSupplyInterval(this.item);
};

/**
 * 有効なスケジュールであるか
 */
Game_ShopSupplySchedule.prototype.isValid = function()
{
    return this._startCount >= 0;
};

/**
 * 補充を行うか
 */
Game_ShopSupplySchedule.prototype.canSupply = function()
{
    return this.getSupplyInterval() > 0;
};

/**
 * 同一と見なせるスケジュールであるか
 */
Game_ShopSupplySchedule.prototype.logicallyEqual = function(rhs)
{
    return rhs != null &&
        this.isValid() &&
        this.inventoryId === rhs.inventoryId &&
        isSameItem(this.item, rhs.item);
};

/**
 * 補充判定用カウントの現在値を取得
 */
Game_ShopSupplySchedule.prototype.getCurrentCountForSupply = function()
{
    switch (getSupplyMode(this.item))
    {
    case SupplyMode.playtime:    return $gameSystem.playtime();
    case SupplyMode.battleCount: return $gameSystem.battleCount();

    default:
        console.error('Invalid supply mode');
        return -1;
    }
};

/**
 * 補充可能な個数を取得
 */
Game_ShopSupplySchedule.prototype.getSuppliableCount = function()
{
    if (!this.isValid() || !this.canSupply())
    {
        return 0;
    }

    var currentCount = this.getCurrentCountForSupply();
    if (currentCount < 0)
    {
        // 異常なモード設定
        this.stop();
        return;
    }

    // 現在のカウントが開始時のカウントより減っている場合、
    // 値が変更されたと見なしてカウントを初期化
    if (currentCount < this._startCount)
    {
        this._startCount = currentCount;
    }

    return Math.floor((currentCount - this._startCount) / this.getSupplyInterval());
};

/**
 * スケジュールの開始
 */
Game_ShopSupplySchedule.prototype.start = function()
{
    if (!this.canSupply())
    {
        debuglog('%1 is not necessary to supply.'.format(this.item.name));
        return;
    }

    var currentCount = this.getCurrentCountForSupply();
    if (currentCount >= 0)
    {
        this._startCount = currentCount;
    }
    else
    {
        // 無効なスケジュール
        this.stop();
    }
};

/**
 * スケジュールの停止
 */
Game_ShopSupplySchedule.prototype.stop = function()
{
    this._startCount = -1;
    debuglog('Schedule [%1:%2] stopped'.format(this.inventoryId, this.item.name));
};

/**
 * 在庫補充処理
 */
Game_ShopSupplySchedule.prototype.supply = function()
{
    if (!this.canSupply())
    {
        this.stop();
        return;
    }

    var count = this.getSuppliableCount();
    if (count <= 0)
    {
        return;
    }

    var item = this.item;
    var inventory = $gameSystem.getInventoryById(this.inventoryId);
    inventory.gainStock(item, count);

    debuglog('%1: Supplied %2'.format(item.name, count));

    if (inventory.isStockFull(item))
    {
        this.stop();
    }
    else
    {
        // 補充した分カウンタを進める
        this._startCount += count * this.getSupplyInterval();
    }
};


//-----------------------------------------------------------------------------
// Game_ShopInventorySupplier
//
// 店舗の在庫補充を制御するクラス

Game_ShopInventorySupplier.prototype.initialize = function()
{
    this._schedules = [];
};

/**
 * 既に同一アイテムのスケジュールが登録済みか
 */
Game_ShopInventorySupplier.prototype.isRegistered = function(schedule)
{
    return this._schedules.some(function(s)
        {
            return s.logicallyEqual(schedule);
        }, this);
};

/**
 * スケジュール登録
 */
Game_ShopInventorySupplier.prototype.register = function(schedule)
{
    if (this.isRegistered(schedule))
    {
        return;
    }

    schedule.start();
    if (schedule.isValid())
    {
        this._schedules.push(schedule);
        debuglog('Schedule for %1 is registered'.format(schedule.item.name));
    }
};

/**
 * 指定したスケジュールを削除
 */
Game_ShopInventorySupplier.prototype.remove = function(schedule)
{
    this._schedules = this._schedules.filter(function(s)
        {
            return !s.logicallyEqual(schedule);
        }, this);
};

/**
 * 停止済みのスケジュールを削除
 */
Game_ShopInventorySupplier.prototype.removeStopped = function()
{
    this._schedules = this._schedules.filter(function(s)
        {
            return s.isValid();
        }, this);
};

/**
 * 在庫の更新
 */
Game_ShopInventorySupplier.prototype.update = function()
{
    this._schedules.forEach(function(s)
    {
        s.supply();
    }, this);

    this.removeStopped();
};


//-----------------------------------------------------------------------------
// Window_Base

/**
 * 店舗在庫数の描画
 */
Window_Base.prototype.drawShopStockNumber = function(item, inventory, x, y, width)
{
    if (!inventory.isStockManaged(item))
    {
        return;
    }

    var valueWidth = this.textWidth('000');
    var slashWidth = this.textWidth('/');
    var captionWidth = this.textWidth(Params.stockCaption) + 8;

    this.changeTextColor(this.systemColor());
    this.drawText(Params.stockCaption, x, y, captionWidth);

    var numX = x + width - (valueWidth * 2 + slashWidth);
    var stock = inventory.getStock(item);
    var stockMax = inventory.getStockMax(item);
    this.resetTextColor();
    this.drawText(stock, numX, y, valueWidth, 'right');
    this.drawText('/', numX + valueWidth, y, slashWidth, 'right');
    this.drawText(stockMax, numX + valueWidth + slashWidth, y, valueWidth, 'right');
};


//-----------------------------------------------------------------------------
// Window_ShopBuy

var _Window_ShopBuy_isEnabled = Window_ShopBuy.prototype.isEnabled;
Window_ShopBuy.prototype.isEnabled = function(item)
{
    var enabled = _Window_ShopBuy_isEnabled.call(this, item);

    if (this._inventory)
    {
        return enabled && this._inventory.isStockAvailable(item);
    }
    else
    {
        return enabled;
    }
};

var _Window_ShopBuy_drawItem = Window_ShopBuy.prototype.drawItem;
Window_ShopBuy.prototype.drawItem = function(index)
{
    var item = this._data[index];
    if (this._inventory && !this._inventory.isStockAvailable(item))
    {
        // 売り切れ表示
        var rect = this.itemRect(index);
        var priceWidth = 96;
        rect.width -= this.textPadding();
        this.changePaintOpacity(this.isEnabled(item));
        this.drawItemName(item, rect.x, rect.y, rect.width - priceWidth);
        this.drawText(
            Params.soldOutText,
            rect.x + rect.width - priceWidth,
            rect.y,
            priceWidth,
            'right');
        this.changePaintOpacity(true);
    }
    else
    {
        _Window_ShopBuy_drawItem.call(this, index);
    }
};

/**
 * 在庫管理オブジェクトの設定
 */
Window_ShopBuy.prototype.setInventory = function(inventory)
{
    this._inventory = inventory;
};


//-----------------------------------------------------------------------------
// Window_ShopNumber

var _Window_ShopNumber_refresh = Window_ShopNumber.prototype.refresh;
Window_ShopNumber.prototype.refresh = function()
{
    _Window_ShopNumber_refresh.call(this);

    if (!Params.showStockInStatus)
    {
        this.drawStockNumber();
    }
};

/**
 * 在庫数の描画
 */
Window_ShopNumber.prototype.drawStockNumber = function()
{
    if (!this._item || !this._inventory)
    {
        return;
    }

    var valueWidth = this.textWidth('000');
    var slashWidth = this.textWidth('/');
    var captionWidth = this.textWidth(Params.stockCaption) + this.textPadding() * 2 + 8;
    var width = captionWidth + valueWidth * 2 + slashWidth;
    var x = this.contents.width - width - this.textPadding() * 2;
    var y = this.stockY();
    this.drawShopStockNumber(this._item, this._inventory, x, y, width);
};

/**
 * 在庫数 Y 座標
 */
Window_ShopNumber.prototype.stockY = function()
{
    return this.itemY() - this.lineHeight() * 2;
};

/**
 * 在庫管理オブジェクトの設定
 */
Window_ShopNumber.prototype.setInventory = function(inventory)
{
    this._inventory = inventory;
};


//-----------------------------------------------------------------------------
// Window_ShopStatus

var _Windowe_ShopStatus_refresh = Window_ShopStatus.prototype.refresh;
Window_ShopStatus.prototype.refresh = function()
{
    _Windowe_ShopStatus_refresh.call(this);

    if (Params.showStockInStatus)
    {
        var x = this.textPadding();
        this.drawStockNumber(x, this.lineHeight());
    }
};

/**
 * 在庫数の描画
 */
Window_ShopStatus.prototype.drawStockNumber = function(x, y)
{
    if (!this._item || !this._inventory)
    {
        return;
    }

    var width = this.contents.width - this.textPadding() * 2;
    this.drawShopStockNumber(this._item, this._inventory, x, y, width);
};

/**
 * 在庫管理オブジェクトの設定
 */
Window_ShopStatus.prototype.setInventory = function(inventory)
{
    this._inventory = inventory;
};


//-----------------------------------------------------------------------------
// Scene_Shop

var _Scene_Shop_prepare = Scene_Shop.prototype.prepare;
Scene_Shop.prototype.prepare = function(goods, purchaseOnly)
{
    _Scene_Shop_prepare.call(this, goods, purchaseOnly);

    // 在庫補充
    $gameSystem.updateInventorySupplier();

    // 予約されている在庫管理情報を呼び出す
    var id = $gameTemp.nextInventoryId;
    if (id != null)
    {
        this._inventory = $gameSystem.getInventoryById(id);
        $gameTemp.nextInventoryId = null;
    }
    else
    {
        this._inventory = null;
    }
};

var _Scene_Shop_createBuyWindow = Scene_Shop.prototype.createBuyWindow;
Scene_Shop.prototype.createBuyWindow = function()
{
    _Scene_Shop_createBuyWindow.call(this);

    this._buyWindow.setInventory(this._inventory);
};

var _Scene_Shop_createNumberWindow = Scene_Shop.prototype.createNumberWindow;
Scene_Shop.prototype.createNumberWindow = function()
{
    _Scene_Shop_createNumberWindow.call(this);

    this._numberWindow.setInventory(this._inventory);
};

var _Scene_Shop_createStatusWindow = Scene_Shop.prototype.createStatusWindow;
Scene_Shop.prototype.createStatusWindow = function()
{
    _Scene_Shop_createStatusWindow.call(this);

    this._statusWindow.setInventory(this._inventory);
};

var _Scene_Shop_maxBuy = Scene_Shop.prototype.maxBuy;
Scene_Shop.prototype.maxBuy = function()
{
    var count = _Scene_Shop_maxBuy.call(this);

    if (this._inventory)
    {
        // 既に所持金に応じた cap がかかっているので、在庫数と比較して少ない方を採用
        count = Math.min(count, this._inventory.getStock(this._item));
    }

    return count;
};

var _Scene_Shop_doBuy = Scene_Shop.prototype.doBuy;
Scene_Shop.prototype.doBuy = function(number)
{
    _Scene_Shop_doBuy.call(this, number);

    // 在庫を減らす
    if (this._inventory)
    {
        this._inventory.loseStock(this._item, number);

        // 在庫補充を開始
        $gameSystem.registerInventorySupplySchedule(this._inventory.id, this._item);
    }
};

var _Scene_Shop_doSell = Scene_Shop.prototype.doSell;
Scene_Shop.prototype.doSell = function(number)
{
    _Scene_Shop_doSell.call(this, number);

    // 買戻し用に在庫を増やす
    if (this._inventory)
    {
        this._inventory.gainStock(this._item, number);
    }
};

})();
