<?php
namespace sammo\Scenario;
use \sammo\Util;
use \sammo\JosaUtil;
use \sammo\DB;
use \sammo\CityHelper;
use \sammo\GameUnitConst;
use \sammo\CityConst;
use \sammo\GameConst;
use \sammo\SpecialityHelper;

class NPC{

    public $generalID = null;
    public $realName = null;

    public $affinity; 
    public $name; 
    public $picturePath; 
    public $nationID; 
    public $locatedCity; 
    public $leadership; 
    public $strength; 
    public $intel; 
    public $officerLevel;
    public $birth; 
    public $death; 
    public $ego;
    public $charDomestic; 
    public $charWar; 
    public $npc = 2;
    public $text;
    static $prefixList = [
        1 => 'ⓝ', //빙의 NPC
        2 => 'ⓝ', //NPC
        3 => 'ⓜ', //인탐 장수
        4 => 'ⓖ', //의병장(전략)
        5 => '㉥', //부대장
        6 => 'ⓤ', //unselectable npc, 빙의 불가 npc
        
        9 => 'ⓞ', //오랑캐?
    ];

    public $gold;
    public $rice;

    protected $specAge = null;
    protected $specAge2 = null;
    protected $experience = null;
    protected $dedication = null;

    public $killturn = null;

    //XXX: 코드 못 바꾸나?
    protected $dex1 = 0;
    protected $dex2 = 0;
    protected $dex3 = 0;
    protected $dex4 = 0;
    protected $dex5 = 0;

    public function __construct(
        int $affinity, 
        string $name, 
        $picturePath, 
        int $nationID, 
        $locatedCity,
        int $leadership, 
        int $strength, 
        int $intel, 
        int $officerLevel = 0,
        int $birth = 160, 
        int $death = 300, 
        $ego = null,
        $char = null, 
        $text = null
    ){
        $this->affinity = $affinity;
        $this->name = $name;
        $this->picturePath = $picturePath;
        $this->nationID = $nationID;
        $this->locatedCity = $locatedCity;
        $this->leadership = $leadership;
        $this->strength = $strength;
        $this->intel = $intel;
        $this->officerLevel = $officerLevel;
        $this->birth = $birth;
        $this->death = $death;
        $this->ego = $ego;
        $this->text = $text;

        $this->gold = GameConst::$defaultGold;
        $this->rice = GameConst::$defaultRice;

        $general = [
            'leadership'=>$leadership,
            'strength'=>$strength,
            'intel'=>$intel
        ];

        $this->charDomestic = GameConst::$defaultSpecialDomestic;
        $this->charWar = GameConst::$defaultSpecialWar;

        if($char === '랜덤전특'){
            $this->charWar = SpecialityHelper::pickSpecialWar($general);
        }
        else if($char === '랜덤내특'){
            $this->charDomestic = SpecialityHelper::pickSpecialDomestic($general);
        }
        else if($char === '랜덤'){
            if(Util::randBool(2/3)){
                $this->charWar = SpecialityHelper::pickSpecialWar($general);
            }
            else{
                $this->charDomestic = SpecialityHelper::pickSpecialDomestic($general);
            }
        }
        else if($char === null){
        }
        else{
            //TODO: 내특, 전특 구분 필요

            try{
                $this->charDomestic = SpecialityHelper::getDomesticClassByName($char);
            }
            catch (\Exception $e) {
                try{
                    $this->charWar = SpecialityHelper::getWarClassByName($char);
                }
                catch (\Exception $e){
                    
                }
                
            }
        }  
    }

    public function setSpecYear(?int $specAge, ?int $specAge2):self{
        $this->specAge = $specAge;
        $this->specAge2 = $specAge2;
        return $this;
    }

    public function setExpDed(?int $experience, ?int $dedication):self{
        $this->experience = $experience;
        $this->dedication = $dedication;
        return $this;
    }

    public function setMoney(int $gold, int $rice):self{
        $this->gold = $gold;
        $this->rice = $rice;
        return $this;
    }

    public function setDex(int $footman, int $archer, int $cavalry, int $wizard, int $siege):self{
        $this->dex1 = $footman;
        $this->dex2 = $archer;
        $this->dex3 = $cavalry;
        $this->dex4 = $wizard;
        $this->dex5 = $siege;
        return $this;
    }

    public function build($env=[]){
        //scenario에 life==1인 경우 수명 제한이 없어지는 모양.

        if(!key_exists('stored_icons', $env)){
            try{
                $text = \file_get_contents(\sammo\ServConfig::getSharedIconPath('../hook/list.json?1'));
                $storedIcons = \sammo\Json::decode($text);
            }
            catch(\Exception $e){
                $storedIcons = [];
            }
    
            $env['stored_icons'] = $storedIcons;
        }

        $isFictionMode = (Util::array_get($env['fiction'], 0)!=0);

        $year = $env['year'];
        $month = $env['month'];
        $age = $year - $this->birth;
        $name = $this->name;

        if($this->death <= $year){
            return true; //죽었으니 넘어간다.
        }
        if($age < GameConst::$adultAge){
            return false; //예약.
        }

        $isNewGeneral = ($age == GameConst::$adultAge);

        $nationID = $this->nationID;
        if($isFictionMode && $isNewGeneral){
            $nationID = 0;
        }

        if(!\sammo\getNationStaticInfo($nationID)){
            $nationID = 0;
        };


        $db = DB::db();

        if($isNewGeneral){
            $josaYi = JosaUtil::pick($name, '이');
            $logger = new \sammo\ActionLogger(0, 0, $year, $month);
            $logger->pushGlobalActionLog("<Y>{$name}</>{$josaYi} 성인이 되어 <S>등장</>했습니다.");
            $logger->flush();
        }

        if($this->ego == null || $isFictionMode){
            $ego = Util::choiceRandom(GameConst::$availablePersonality);
        }
        else{
            $ego = Util::getClassName(\sammo\getPersonalityClass($this->ego));
        }
        
        $affinity = $this->affinity;

        $charWar = $this->charWar;
        $charDomestic = $this->charDomestic;

        if($affinity === 0 || $isFictionMode){
            $affinity = mt_rand(1, 150);
        }

        if($isFictionMode){
            $charWar = GameConst::$defaultSpecialWar;
            $charDomestic = GameConst::$defaultSpecialDomestic;
        }

        $name = (static::$prefixList[$this->npc]?:'ⓧ').$this->name;

        $duplicateCnt = $db->queryFirstField('SELECT count(no) FROM general WHERE name LIKE %s', $name.'%') + 1;

        if($duplicateCnt > 1){
            $name = "{$name}{$duplicateCnt}";   
        }

        $this->realName = $name;

        $picturePath = $this->picturePath;
        if($env['show_img_level'] < 3){
            $picturePath = 'default.jpg';
        }
        else if(is_numeric($picturePath)){
            if($picturePath < 0){
                $picturePath = null;
            }
            else if(\key_exists($picturePath, $env['stored_icons']['.']??[])){
                $picturePath = $env['stored_icons']['.'][$picturePath];
            }
            else{
                $picturePath = null;
            }
        }
        else if($picturePath !== null && in_array($picturePath, $env['stored_icons'][$env['icon_path']??'.']??[])){
            $picturePath = ($env['icon_path']??'.').'/'.$picturePath;
        }
        else if($picturePath === null && \key_exists('stored_icons', $env)){
            $target = $env['stored_icons']??[];
            $target = $target[$env['icon_path']??'.']??[];
            $picturePath = $target[$this->name]??null;
            if($picturePath){
                $picturePath = ($env['icon_path']??'.').'/'.$picturePath;
            }
        }


        if($picturePath === null){
            $picturePath = 'default.jpg';
        }

        $city = $this->locatedCity;
        if(is_int($city)){
            $city = CityConst::byID($city)->id??null;
        }
        else if(is_string($city)){
            $city = CityConst::byName($city)->id??null;
        }
        if($city === null){
            if($nationID == 0 || !CityHelper::getAllNationCities($nationID)){
                $cityObj = Util::choiceRandom(CityHelper::getAllCities());
            }
            else{
                $cityObj = Util::choiceRandom(CityHelper::getAllNationCities($nationID));
            }
            '@phan-var array<string,string|int> $cityObj';
            $city = $cityObj['id'];
        }
        

        $experience = $this->experience?:$age * 100;
        $dedication = $this->dedication?:$age * 100;
        $officerLevel = $this->officerLevel;
        if(!$officerLevel || $isNewGeneral){
            $officerLevel = $nationID?1:0;
        }

        $turntime = \sammo\getRandTurn($env['turnterm'], new \DateTimeImmutable($env['turntime']));

        if($this->killturn){
            $killturn = $this->killturn;
        }
        else{
            $killturn = ($this->death - $year) * 12 + mt_rand(0, 11) + $month - 1;
        }

        $specage = $this->specAge?:($age + 1);
        $specage2 = $this->specAge2?:($age + 1);

        $db->insert('general',[
            'npc'=>$this->npc,
            'npc_org'=>$this->npc,
            'affinity'=>$affinity,
            'name'=>$name,
            'picture'=>$picturePath,
            'nation'=>$nationID,
            'city'=>$city,
            'leadership'=>$this->leadership,
            'strength'=>$this->strength,
            'intel'=>$this->intel,
            'experience'=>$experience,
            'dedication'=>$dedication,
            'officer_level'=>$officerLevel,
            'gold'=>$this->gold,
            'rice'=>$this->rice,
            'crew'=>0,
            'crewtype'=>GameUnitConst::DEFAULT_CREWTYPE,
            'train'=>0,
            'atmos'=>0,
            'turntime'=>$turntime,
            'killturn'=>$killturn,
            'age'=>$age,
            'belong'=>1,
            'personal'=>$ego,
            'special'=>$charDomestic,
            'specage'=>$specage,
            'special2'=>$charWar,
            'specage2'=>$specage2,
            'npcmsg'=>$this->text,
            'makelimit'=>0,
            'bornyear'=>$this->birth,
            'deadyear'=>$this->death,
            'dex1'=>$this->dex1,
            'dex2'=>$this->dex2,
            'dex3'=>$this->dex3,
            'dex4'=>$this->dex4,
            'dex5'=>$this->dex5,
        ]);
        $this->generalID = $db->insertId();
        $turnRows = [];
        foreach(Util::range(GameConst::$maxTurn) as $turnIdx){
            $turnRows[] = [
                'general_id'=>$this->generalID,
                'turn_idx'=>$turnIdx,
                'action'=>'휴식',
                'arg'=>null,
                'brief'=>'휴식',
            ];
        }
        $db->insert('general_turn', $turnRows);

        $rank_data = [];
        foreach(array_keys(\sammo\General::RANK_COLUMN) as $rankColumn){
            $rank_data[] = [
                'general_id'=>$this->generalID,
                'nation_id'=>0,
                'type'=>$rankColumn,
                'value'=>0
            ];
        }
        $db->insert('rank_data', $rank_data);
        $db->insert('betting', [
            'general_id'=>$this->generalID,
        ]);

        return true; //생성되었다.
    }
}