<?php
namespace sammo;

class ScoutMessage extends Message{

    const ACCEPTED = 1;
    const DECLINED = -1;
    const INVALID = 0;
    protected $validScout = true;

    public function __construct(
        string $msgType,
        MessageTarget $src,
        MessageTarget $dest,
        string $msg,
        \DateTime $date,
        \DateTime $validUntil,
        array $msgOption
    )
    {
        if ($msgType !== self::MSGTYPE_PRIVATE){
            throw new \InvalidArgumentException('DiplomaticMessage msgType');
        }

        if(Util::array_get($msgOption['action']) !== 'scout'){
            throw new \InvalidArgumentException('Action !== scout');
        }

        parent::__construct(...func_get_args());
        
        if(Util::array_get($msgOption['used'])){
            $this->validScout = false;
        }

        if($this->validUntil <= new \DateTime()){
            $this->validScout = false;
        }
    }

    protected function checkScoutMessageValidation(int $receiverID){
        if(!$this->validScout){
            return [self::INVALID, '유효하지 않은 등용장입니다.'];
        }
        if($this->mailbox !== $this->dest->generalID){
            return [self::INVALID, '송신자가 등용장을 처리할 수 없습니다.'];
        }

        if($this->mailbox !== $receiverID){
            return [self::INVALID, '올바른 수신자가 아닙니다.'];
        }

        return [self::ACCEPTED, ''];
    }

    /**
     * @return int 수행 결과 반환, ACCEPTED(등용장 소모), DECLINED(등용장 소모), INVALID 중 반환
     */
    public function agreeMessage(int $receiverID, string &$reason):int{
        //NOTE: 올바른 유저가 agreeMessage() 호출을 한건지는 외부에서 체크 필요(Session->userID 등)

        if(!$this->id){
            throw \RuntimeException('전송되지 않은 메시지에 수락 진행 중');
        }

        list($result, $reason) = $this->checkScoutMessageValidation($receiverID);

        if($result !== self::ACCEPTED){
            pushGenLog(['no'=>$receiverID], ["<C>●</>{$reason} 등용 수락 불가."]);
            if($result === self::DECLINED){
                $this->_declineMessage();
            }
            return $result;
        }

        $helper = new Engine\Personnel($this->src->nationID, $this->src->generalID);

        list($result, $reason) = $helper->scoutGeneral($receiverID);

        if($result !== self::ACCEPTED){
            pushGenLog(['no'=>$receiverID], ["<C>●</>{$reason} 등용 수락 불가."]);
            if($result === self::DECLINED){
                $this->_declineMessage();
            }
            return $result;
        }

        //메시지 비 활성화
        $this->msgOption['used'] = true;
        $this->invalidate();
        $this->validScout = false;

        $josaRo = JosaUtil::pick($this->src->nationName, '로');
        $josaYi = JosaUtil::pick($this->dest->generalName, '이');
        pushGenLog(
            ['no'=>$this->dest->generalID],
            ["<C>●</><D>{$this->src->nationName}</>{$josaRo} 망명하여 수도로 이동합니다."]);
        pushGenLog(
            ['no'=>$this->src->generalID], 
            ["<C>●</><Y>{$this->dest->generalName}</> 등용에 성공했습니다."]
        );
        pushGeneralHistory(
            ['no'=>$this->src->generalID],
            "<C>●</>{$helper->year}년 {$helper->month}월:<Y>{$this->dest->generalName}</> 등용에 성공");
        pushGeneralHistory(
            ['no'=>$this->dest->generalID],
            "<C>●</>{$helper->year}년 {$helper->month}월:<D>{$this->src->nationName}</>{$josaRo} 망명"
        );
        pushGeneralPublicRecord(
            ["<C>●</>{$helper->month}월:<Y>{$this->dest->generalName}</>{$josaYi} <D><b>{$this->src->nationName}</b></>{$josaRo} <S>망명</>하였습니다."], 
            $helper->year, 
            $helper->month
        );

        $newMsg = new Message(
            self::MSGTYPE_PRIVATE, 
            $this->src, 
            $this->dest, 
            "{$this->src->nationName}{$josaRo} 등용 제의 수락",
            new \DateTime(),
            new \DateTime('9999-12-31'),
            [
                'delete'=>$this->id
            ]
        );
        $newMsg->send(true);

        return self::ACCEPTED;
    }

    protected function _declineMessage(){
        $this->msgOption['used'] = true;
        $this->invalidate();
        $this->validScout = false;

        $josaRo = JosaUtil::pick($this->src->nationName, '로');
        $newMsg = new Message(
            self::MSGTYPE_PRIVATE, 
            $this->src, 
            $this->dest, 
            "{$this->src->nationName}{$josaRo} 등용 제의 거부",
            new \DateTime(),
            new \DateTime('9999-12-31'),
            [
                'delete'=>$this->id
            ]
        );
        $newMsg->send(true);

        return self::DECLINED;
    }

    public function declineMessage(int $receiverID, string &$reason):int{
        if(!$this->id){
            throw \RuntimeException('전송되지 않은 메시지에 거절 진행 중');
        }

        list($result, $reason) = $this->checkScoutMessageValidation($receiverID);

        if($result === self::INVALID){
            pushGenLog(['no'=>$receiverID], ["<C>●</>{$reason} 등용 취소 불가."]);
            return $result;
        }

        $josaRo = JosaUtil::pick($this->src->nationName, '로');
        $josaYi = JosaUtil::pick($this->dest->generalName, '이');
        pushGenLog(['no'=>$receiverID], "<C>●</><D>{$this->src->nationName}</>{$josaRo} 망명을 거부했습니다.");
        pushGenLog(['no'=>$this->src->generalID], "<C>●</><Y>{$this->dest->generalName}</>{$josaYi} 등용을 거부했습니다.");
        $this->_declineMessage();        

        return self::DECLINED;
    }

    public static function buildScoutMessage(int $srcGeneralID, int $destGeneralID, &$reason = null, \DateTime $date = null):?self{
        if($srcGeneralID == $destGeneralID){
            if($reason !== null){
                $reason = '같은 장수에게 등용장을 보낼 수 없습니다';
            }
            return null;
        }

        $db = DB::db();
        $srcGeneral = $db->queryFirstRow('SELECT `name`, nation FROM general WHERE `no`=%i', $srcGeneralID);
        $destGeneral = $db->queryFirstRow('SELECT `name`, nation, `level` FROM general WHERE `no`=%i', $destGeneralID);
        if($date === null){
            $date = new \DateTime();
        }

        if($destGeneral['level'] == 12){
            if($reason !== null){
                $reason = '군주에게 등용장을 보낼 수 없습니다';
            }
            return null;
        }

        if(!$srcGeneral['nation']){
            if($reason !== null){
                $reason = '재야 상태일 때에는 등용장을 보낼 수 없습니다';
            }
            return null;
        }

        if($srcGeneral['nation'] === $destGeneral['nation']){
            if($reason !== null){
                $reason = '같은 소속의 장수에게 등용장을 보낼 수 없습니다';
            }
            return null;
        }

        $srcNationInfo = getNationStaticInfo($srcGeneral['nation']);
        $destNationInfo = getNationStaticInfo($destGeneral['nation']);

        $src = new MessageTarget(
            $srcGeneralID, 
            $srcGeneral['name'],
            $srcGeneral['nation'], 
            $srcNationInfo['name'], 
            $srcNationInfo['color']
        );

        $dest = new MessageTarget(
            $destGeneralID, 
            $destGeneral['name'],
            $destGeneral['nation'],
            $destNationInfo['name'], 
            $destNationInfo['color']
        );

        $josaRo = JosaUtil::pick($src->nationName, '로');
        $msg = "{$src->nationName}{$josaRo} 망명 권유 서신";
        $validUntil = new \DateTime("9999-12-31 12:59:59");

        $msgOption = [
            'action'=>'scout'
        ];

        return new ScoutMessage(Message::MSGTYPE_PRIVATE, $src, $dest, $msg, $date, $validUntil, $msgOption);
    }
}