<?php

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

namespace Game\Model;

use Game\Constant\EventTypeDefine;
use Game\Constant\GameConstantDefine;
use Game\Data\AccountData;
use Game\Data\MoneyData;
use Game\Logic\EventLogic;
use Game\Method\Player\PlayerBuffLogic;
use Game\Operation\EventLog\AddItemLog;
use Game\Operation\EventLog\ConsumeItemLog;
use Game\Operation\EventLog\EventLog_Manager;
use Game\Operation\EventLog\EventLogType;

class MoneyModel
{
    use PlayerBuffLogic;
    use EventLogic;

    /**
     * 货币类型， 金币
     */
    public const TYPE_GOLD = 100001;
    /**
     * 货币类型，点券
     */
    public const TYPE_TICKETS = 100002;

    /**
     * 货币类型，钻石
     */
    public const TYPE_DIAMOND = 100003;

    /**
     * 货币类型, 俱乐部代币
     */
    public const TYPE_CLUB = 100004;

    /**
     * 货币类型, 俱乐部代币
     */
    public const TYPE_SEASON = 100005;

    /**
     * 货币类型, 赛季战令代币
     */
    public const TYPE_ZL = 100006;

    public const TYPE_MONEY_MAP = [
        self::TYPE_GOLD,
        self::TYPE_TICKETS,
        self::TYPE_DIAMOND,
        self::TYPE_CLUB,
        self::TYPE_SEASON,
        self::TYPE_ZL,
    ];

    public const TYPE_MAX = 100006;

    private ?MoneyData $data = null;

    public const MAX_LIMIT = 4200000000;

    public int $playerId;

    private int $logTaskId = 0; //获得道具任务id
    private int $logAddItemSource = 0;  //获得道具来源
    private int $logConsumeItemSource = 0;  //消耗道具来源

    public function setPlayerId($playerId): void
    {
        $this->playerId = $playerId;
    }

    public function checkType($moneyType): bool
    {
        return !($moneyType < 0 || $moneyType > self::TYPE_MAX);
    }

    /**
     * 加钱
     */
    public function earn($moneyType, $moneyValue): bool
    {
        if ($moneyValue < 0) {
            return false;
        }
        if ($this->init() == false) {
            return false;
        }
        $val = $this->search($moneyType);
        if ($val + $moneyValue > self::MAX_LIMIT) {
            return false;
        }
        $this->data->addMoney($moneyType, $this->getMoneyBuffAddition($moneyType, $moneyValue));
        //记录打点日志
        $log = EventLog_Manager::getInstance()->getEventLog(EventLogType::ItemAdd);
        if (!is_null($log)) {
            /**
             * @var AddItemLog $log
             */
            $log->itemId = $moneyType;
            $log->addNum = $moneyValue;
            $log->newNum = $this->search($moneyType);
            $log->expireTime = 0;
            $log->source = 1;
            $log->taskId = $this->logTaskId;
            $log->source = $this->logAddItemSource;
            $log->markLog();
        }
        return true;
    }

    /**
     * 重置
     */
    public function reset($moneyType): bool {
        if ($this->init() == false) {
            return false;
        }
        $oldNum = $this->search($moneyType);
        $this->data->resetMoney($moneyType);
        //记录打点日志
        $log = EventLog_Manager::getInstance()->getEventLog(EventLogType::ItemConsume);
        if (!is_null($log)) {
            /**
             * @var ConsumeItemLog $log
             */
            $log->itemId = $moneyType;
            $log->costNum = $oldNum;
            $log->newNum = 0;
            $log->source = $this->logConsumeItemSource;
            $log->markLog();
        }
        return true;
    }

    public function saveDB(): bool
    {
        if ($this->data == null) {
            return false;
        }
        return $this->data->updateDB();
    }

    /**
     * 花钱
     * @param $moneyType
     * @param $moneyValue
     * @return bool
     */
    public function cost($moneyType, $moneyValue): bool
    {
        if ($moneyValue < 0) {
            return false;
        }
        if ($this->init() == false) {
            return false;
        }
        $val = $this->search($moneyType);
        if ($val - $moneyValue < 0) {
            return false;
        }
        $this->data->subMoney($moneyType, $moneyValue);
        //触发任务
        $eventData = array(
            GameConstantDefine::EVENT_KEY_MONEY => $moneyType,
            GameConstantDefine::EVENT_KEY_NUM => $moneyValue,
        );
        $this->triggerEvent(EventTypeDefine::EVENT_TYPE_TASK_COST_MONEY, $eventData);
        //记录打点日志
        $log = EventLog_Manager::getInstance()->getEventLog(EventLogType::ItemConsume);
        if (!is_null($log)) {
            /**
             * @var ConsumeItemLog $log
             */
            $log->itemId = $moneyType;
            $log->costNum = $moneyValue;
            $log->newNum = $this->search($moneyType);
            $log->source = $this->logConsumeItemSource;
            $log->markLog();
        }
        return true;
    }

    public function search($moneyType): int
    {
        if ($this->init() == false) {
            return 0;
        }
        switch ($moneyType) {
            case self::TYPE_GOLD:
                return $this->data->gold;
            case self::TYPE_TICKETS:
                return $this->data->tickets;
            case self::TYPE_DIAMOND:
                return $this->data->diamond;
            case self::TYPE_CLUB:
                return $this->data->club;
            case self::TYPE_SEASON:
                return $this->data->season;
            case self::TYPE_ZL:
                return $this->data->warToken;
        }
        return 0;
    }

    private function init(): bool
    {
        if ($this->data != null) {
            return true;
        }
        $this->data = new MoneyData($this->playerId);
        if ($this->data->loadFromDB(0)) {
            return true;
        }
        unset($this->data);
        $this->data = null;
        return  false;
    }

    //打点日志
    public function setLogTaskId(int $taskId)
    {
        $this->logTaskId = $taskId;
    }

    public function clearTaskId()
    {
        $this->logTaskId = 0;
    }

    public function setLogAddItemSource(int $source)
    {
        $this->logAddItemSource = $source;
    }

    public function clearLogAddItemSource()
    {
        $this->logAddItemSource = 0;
    }

    public function setLogConsumeItemSource(int $source)
    {
        $this->logConsumeItemSource = $source;
    }

    public function clearLogConsumeItemSource()
    {
        $this->logConsumeItemSource = 0;
    }

    //检查收益buff
    private function getMoneyBuffAddition($moneyType, $moneyValue): int
    {
        switch ($moneyType)
        {
            case self::TYPE_GOLD:
                //双倍金币收益
                if ($this->checkBuffActivate(AccountData::DB_BUFF_DOUBLE_GOLD) &&
                in_array($this->logAddItemSource, GameConstantDefine::DOUBLE_GOLD_ADD_SOURCE))
                {
                    $moneyValue *= 2;
                }
                break;
        }
        return $moneyValue;
    }
}
