<?php

namespace loyalsoft;

/**
 * 任务步骤, 用于任务卡功能(三组合一)
 * @author gwang(wanggangzero@qq.com)
 */
class Ins_TaskStep extends Object_ext {

    /**
     * @var type 查询用的id
     */
    public $typeId = 0;

    /**
     * @var int 计数器
     */
    public $cur = 0;

    /**
     * @var int start/finish act已执行(0:startAct未执行,1:StartAct已执行且finishAct未执行,2:finishAct已执行)
     */
    public $actState = 0;

    /**
     * @return \sm_task_step mo 获取对应的模板数据
     */
    public function mo() {
        $mo = GameConfig::task_step_getItem($this->typeId);
        my_Assert(null != $mo, ErrCode::err_const_no);
        return $mo;
    }

    /**
     * @return int 计数最大值
     */
    public function max() {
        return $this->mo()->num;
    }

    /**
     * @return string[] 参数数组
     */
    private function paras() {
        return explode(',', $this->mo()->paras);
    }

    /**
     * @return float 当前进度
     */
    public function progress() {
        return $this->cur / $this->max();
    }

    /**
     * 是否完成
     * @return bool
     */
    public function isFinish() {
        return $this->cur >= $this->max();
    }

    /**
     * 执行任务完成事件
     */
    public function doFinishAct() {
//        if ($this->mo()->finishact > 0) {
//            $act = GameConfig::eventAction_getItem($this->mo()->finishact);
//            $this->execAct($act);
//        }
        $this->actState = 2;
    }

    /**
     * 
     * @param \sm_eventAction $act
     */
    private function execAct($act) {
        my_Assert($act, ErrCode::err_const_no);
        switch ($act->cmd) {
            case Enum_EventActionType::StartPlotScene:                          # 触发场景剧情,
            case Enum_EventActionType::StartPlotNPC:                            # 触发NPC剧情
                $paras = explode(',', $act->parameters);                        # 解析下参数
                $arr = GameConfig::plot_getItem($paras[0], $paras[1]);          # 查找对应的剧情
                foreach ($arr as $plot) {
                    isEditor() and $plot = new \sm_plot();
                    if (!empty($plot->presentItem)) {
                        if (strtolower($plot->presentItem) == strtolower("unlockBuild")) { # 特殊处理, 剧情中解锁建筑
                            req()->userInfo->game->privateState->unlockedBuild[] = $plot->presentEffect;
                        } else if (strtolower($plot->presentItem) == strtolower("rename")) {
                            // 跳过特殊字符串
                        } else {
                            StoreProc::AddMultiItemInStore($plot->presentItem);
                        }
                    }
                    if (!empty($plot->recycleItem)) {
                        $val = explode(",", $plot->recycleItem);
                        my_Assert(count($val) > 1, "解析回收道具字符串出错");
                        StoreProc::removeItemFromStore(req()->userInfo->game->store, $val[0], $val[1]);
                    }
                }
                break;
            case Enum_EventActionType::UnlockBuild:                             # 解锁建筑
                req()->userInfo->game->privateState->unlockedBuild[] = $act->parameters;
                break;
        }
    }

    /**
     * 执行任务开始事件
     */
    public function doStartAct() {
//        if ($this->mo()->startact > 0) {
//            $act = GameConfig::eventAction_getItem($this->mo()->startact);
//            $this->execAct($act);
//        }
        $this->actState = 1;
    }

    /**
     * 构造函数
     * @param type $args
     */
    public function __construct($args) {
        if (isInt($args)) {
            $this->typeId = $args;
        } else {
            parent::__construct($args);
        }
    }

    /**
     * 是否状态型任务
     * @param type $cmd
     */
    function isStatusType() {
        return $this->mo()->cmd == Enum_TaskCmdType::GainItem                   # 获取道具
                || $this->mo()->cmd == Enum_TaskCmdType::HeroLevelUpTo          # 提升玩家等级到x
                || $this->mo()->cmd == Enum_TaskCmdType::CommanderLevelUpTo;
    }

    /**
     * 自动对齐可能出现统计失误的状态型任务计数
     * @return boolean 是否有修改
     */
    function autoCalcStatusCur() {
        if ($this->isStatusType()) {
            $mo = $this->mo();
            if ($mo != null) {
                $cur = $this->calcStatusCur();
                if ($cur > $this->max()) {
                    $cur = $this->max();
                }
                if ($this->cur != $cur) {
                    $this->cur = $cur;
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @return int 计算状态类的进度
     */
    function calcStatusCur() {
        $mo = $this->mo();
        $paras = $this->paras();
        $para0 = "";
        $para1 = "";
        $para2 = "";

        if (count($paras) >= 1) {
            $para0 = $paras[0];
        }

        if (count($paras) >= 2) {
            $para1 = $paras[1];
        }

        if (count($paras) >= 3) {
            $para2 = $paras[2];
        }

        switch ($mo->cmd) {
            case Enum_TaskCmdType::GainItem:                                    # 收集道具
                $store = new Info_Store(req()->userInfo->game->store);
                return $store->GetItemCount($para0);
            case Enum_TaskCmdType::CommanderLevelUpTo:
                $lvl = ctx()->base()->level;
                return $lvl;
            case Enum_TaskCmdType::HeroLevelUpTo:
                $heros = new Info_UserGameHero(req()->userInfo->game->heros);
                $hero = $heros->GetHeroByMoID($para0);
                if (null != $hero) {
                    return $hero->level;
                }
                break;
        }
        return 0;
    }

    /**
     * 检查任务条件(与petmini采用相同的参数和判定方法2020年12月12日11:38:02)
     * @param Ins_TaskEventArgs $taskCardEvent
     * @return bool
     */
    public function check_new($taskCardEvent) {
//        var_dump($taskCardEvent);
        if ($taskCardEvent->taskType != $this->mo()->cmd) {                     # 事件类型匹配
            return false;
        }
        if ($this->isStatusType()) {                                            # 状态检查类任务
            return $this->autoCalcStatusCur();
        }
        if ($this->isFinish()) {
            return false;
        }
        if (strlen($this->mo()->paras) <= 0) {                                  # 无参数
            return true;
        }

        $paras = $this->paras();
        $index = 0;
        foreach ($taskCardEvent->paras as $para) {                              # 其他任务, 执行参数判定
            if ($index < count($paras)) {
                if (strpos($para, "|") !== false) {                             # 某个条件是"或"的关系, 即有多重可能值, 满足其一即可
                    $paraList = explode("|", $para);
                    foreach ($paraList as $paraItem) {
                        if ($paraItem == $paras[$index]) {
                            continue;                                           # 满足某一个即可, 继续判断下一个条件.
                        }
                    }
                } else {                                                        # only one, 不存在"或"的判定
                    if ($paras[$index] != 0 && $para != $paras[$index]) {       # 直接匹配
                        return false;                                           # 一但没匹配上, 直接返回false就好了.
                    }
                }
            }                                                                   # 参数中多余的数据就直接跳过,不比较了(因为自己不需要判断那么多参数)
            $index++;
        }
        return true;                                                            # 走到最后则判定满足条件.
    }

    /**
     * 推进任务进度(采用和petmini相同的推进算法,2020年12月12日11:38:22)
     * @param Ins_TaskEventArgs $taskParam
     */
    public function propel($taskParam) {
//        var_dump($taskParam);
        switch ($taskParam->ope) {
            case Enum_PropelType::set:
                $this->cur = $taskParam->val;
                break;
            case Enum_PropelType::add:
                $this->cur += $taskParam->val;
                break;
            case Enum_PropelType::inc:
                $this->cur += 1;
                break;
            case Enum_PropelType::max:
                if ($taskParam->val > $this->cur) {
                    $this->cur = $taskParam->val;
                }
                break;
            case Enum_PropelType::stat:

                break;
        }
    }

}
