<?php

/**
 * MoneyLogic.php
 * 文件描述
 * Created On 2022/1/24
 * @author yuanb yuanbo0x@gmail.com
 */

namespace Game\Logic;

use Framework\Log\LogMark;
use Framework\MVC\ModelManager;
use Framework\Network\SendMessage;
use Game\Constant\ClientErrorCode;
use Game\Constant\ConstTemplate\TemplateItem;
use Game\Constant\GameErrorCode;
use Game\Constant\ModelTypeDefine;
use Game\Constant\TemplateDefine;
use Game\Model\MoneyModel;
use Game\Protobuf\GainMoneySingle;
use Game\Protobuf\PacketId;
use Game\Protobuf\SyncChangeMoney;
use Framework\Logic\PacketCacheLogic;

trait MoneyLogic
{
    use PacketCacheLogic;
    public function addMoney(int $moneyType, int $addValue): bool
    {
        if(!$this->addMoneyLogic($moneyType, $addValue)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[logic] game add money error!',
                ['moneyType' => $moneyType, 'addValue' => $addValue]
            );
            return false;
        }
        $this->syncChangeMoney([$moneyType]);
        return true;
    }

    public function gmAddMoney(int $moneyType, int $addValue): bool
    {
        $num = $this->getMoney($moneyType);
        $cfg = $this->getTitle(TemplateDefine::TYPE_ITEM, $moneyType);
        if(($num + $addValue) > $cfg[TemplateItem::MaxNumb]) {
            return false;
        }
        if(!$this->addMoneyLogic($moneyType, $addValue)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[logic] gm game add money error!',
                ['moneyType' => $moneyType, 'addValue' => $addValue]
            );
            return false;
        }
        $this->addMoneyPacket([$moneyType]);
        return true;
    }

    public function addMoneyLogic(int $moneyType, int $addValue): bool {
        /**
         * @var MoneyModel $money
         */
        $money = ModelManager::getInstance()->getModel(ModelTypeDefine::MONEY);
        if ($money->checkType($moneyType) == false) {
            return false;
        }
        if ($money->earn($moneyType, $addValue) == false) {
            return false;
        }
        return $money->saveDB();
    }

    public function addMoneyList(array $arr): bool
    {
        /**
         * @var MoneyModel $money
         */
        $money = ModelManager::getInstance()->getModel(ModelTypeDefine::MONEY);
        $syncMessage = array();
        foreach ($arr as $moneyType => $addValue) {
            if ($money->checkType($moneyType) == false) {
                return false;
            }
            if ($money->earn($moneyType, $addValue) == false) {
                return false;
            }
            array_push($syncMessage, $moneyType);
        }
        $this->syncChangeMoney($syncMessage);
        return $money->saveDB();
    }

    public function subMoney(int $moneyType, int $addValue): bool
    {
        if(!$this->subMoneyLogic($moneyType, $addValue)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[logic] game sub money error!',
                ['moneyType' => $moneyType, 'addValue' => $addValue]
            );
            return false;
        }
        $this->syncChangeMoney([$moneyType]);
        return true;
    }

    public function gmSubMoney(int $moneyType, int $addValue): bool
    {
        if(!$this->subMoneyLogic($moneyType, $addValue)) {
            LogMark::getInstance()->markError(
                GameErrorCode::DATA_UPDATE_ERROR,
                '[logic] gm sub money error!',
                ['moneyType' => $moneyType, 'addValue' => $addValue]
            );
            return false;
        }
        $this->addMoneyPacket([$moneyType]);
        return true;
    }

    public function subMoneyLogic(int $moneyType, int $addValue): bool
    {
        /**
         * @var MoneyModel $money
         */
        $money = ModelManager::getInstance()->getModel(ModelTypeDefine::MONEY);
        if ($money->checkType($moneyType) == false) {
            return false;
        }
        if ($money->cost($moneyType, $addValue) == false) {
            return false;
        }
        return $money->saveDB();
    }

    public function subMoneyList(array $arr): bool
    {
        /**
         * @var MoneyModel $money
         */
        $money = ModelManager::getInstance()->getModel(ModelTypeDefine::MONEY);
        $syncMessage = array();
        foreach ($arr as $moneyType => $addValue) {
            if ($money->checkType($moneyType) == false) {
                return false;
            }
            if ($money->cost($moneyType, $addValue) == false) {
                return false;
            }
            array_push($syncMessage, $moneyType);
        }
        $this->syncChangeMoney($syncMessage);
        return $money->saveDB();
    }

    public function getMoney($moneyType): int
    {
        /**
         * @var MoneyModel $money
         */
        $money = ModelManager::getInstance()->getModel(ModelTypeDefine::MONEY);
        if ($money->checkType($moneyType) == false) {
            return 0;
        }
        return $money->search($moneyType);
    }

    private function addMoneyPacket(array $moneyType)
    {
        /**
         * @var MoneyModel $money
         */
        $money = ModelManager::getInstance()->getModel(ModelTypeDefine::MONEY);
        $syncMessage = array();
        if (!empty($moneyType)) {
            foreach($moneyType as $t) {
                $changeMoney = new GainMoneySingle();
                $changeMoney->setId($t);
                $changeMoney->setNum($money->search($t));
                array_push($syncMessage, $changeMoney);
            }
            $sendMessage = new SyncChangeMoney();
            $sendMessage->setMoney($syncMessage);
            $this->addPacket(PacketId::Sync_Change_Money, $sendMessage);
        }
    }

    private function syncChangeMoney(array $moneyType)
    {
        /**
         * @var MoneyModel $money
         */
        $money = ModelManager::getInstance()->getModel(ModelTypeDefine::MONEY);
        $syncMessage = array();
        if (!empty($moneyType)) {
            foreach($moneyType as $t) {
                $changeMoney = new GainMoneySingle();
                $changeMoney->setId($t);
                $changeMoney->setNum($money->search($t));
                array_push($syncMessage, $changeMoney);
            }
            $sendMessage = new SyncChangeMoney();
            $sendMessage->setMoney($syncMessage);
            SendMessage::getInstance()->sendClient(PacketId::Sync_Change_Money, $sendMessage);
        }
    }

    // 货币不足错误码
    public function getMoneyNotEnoughCode(int $moneyType): int
    {
        switch ($moneyType)
        {
            case MoneyModel::TYPE_GOLD:
                return ClientErrorCode::MONEY_GOLD_NOT_ENOUGH;
            case MoneyModel::TYPE_TICKETS:
                return ClientErrorCode::MONEY_TICKETS_NOT_ENOUGH;
            case MoneyModel::TYPE_DIAMOND:
                return ClientErrorCode::MONEY_DIAMOND_NOT_ENOUGH;
            case MoneyModel::TYPE_CLUB:
                return ClientErrorCode::MONEY_CLUB_NOT_ENOUGH;
            case MoneyModel::TYPE_SEASON:
                return ClientErrorCode::MONEY_SEASON_NOT_ENOUGH;
        }
    }
}
