<?php

    require_once($path["entity"] . "Entity.php");
    require_once($path["entity"] . "K_Unit.php");
    require_once($path["entity"] . "Rune.php");


    /**
     * A Unit.
     *
     * Represents an object from the table 'unit'.
     */
    class Unit extends Entity{

        /**
         * Owner identifier.
         */
        public $uid;

        /**
         * Monster identifier.
         */
        public $id;

        /**
         * {@see Building} the unit is in.
         */
        public $building;

        /**
         * Base {@see K_Unit}.
         */
        public $unit;

        /**
         * Unit stars.
         */
        public $stars;

        /**
         * Unit level.
         */
        public $level;

        /**
         * Monster base HP stat.
         */
        public $hp;

        /**
         * Monster base ATK stat.
         */
        public $attack;

        /**
         * Monster base DEF stat.
         */
        public $defense;

        /**
         * Monster base SPD stat.
         */
        public $speed;

        /**
         * Monster base CRR stat.
         */
        public $crit_rate;

        /**
         * Monster base CRD stat.
         */
        public $crit_damage;

        /**
         * Monster base RES stat.
         */
        public $resistance;

        /**
         * Monster base ACC stat.
         */
        public $accuracy;

        /**
         * Total gained experience.
         */
        public $experience;

        /**
         * Total gained experience in its current level.
         */
        public $exp_gained;

        /**
         * Experience / hour in the current building.
         */
        public $exp_gain_rate;

        /**
         * Equipped transmogification.
         */
        public $costume;

        /**
         * Unit attribute
         */
        public $attribute;

        /**
         * {@see K_Source} the unit was aquired from.
         */
        public $source;

        /**
         * Datetime the unit was obtained.
         */
        public $create_time;

        /**
         * Indicates if the unit is a Homunculus
         */
        public $homunculus;

        /**
         * Indicates the Homunculus name
         */
        public $homunculus_name;

        /**
         * Indicates if the monster is locked.
         */
        public $lock;

        /**
         * Unit rune HP stat.
         */
        public $rune_hp = 0;

        /**
         * Unit rune ATK stat.
         */
        public $rune_attack = 0;

        /**
         * Unit rune DEF stat.
         */
        public $rune_defense = 0;

        /**
         * Unit rune SPD stat.
         */
        public $rune_speed = 0;

        /**
         * Unit rune CRR stat.
         */
        public $rune_crit_rate = 0;

        /**
         * Unit rune CRD stat.
         */
        public $rune_crit_damage = 0;

        /**
         * Unit rune RES stat.
         */
        public $rune_resistance = 0;

        /**
         * Unit rune ACC stat.
         */
        public $rune_accuracy = 0;

        /**
         * Average rune efficiency.
         */
        public $avg_rune_efficiency;

        /**
         * Equiped {@see Rune}s
         */
        public $rune = [];

        /**
         * Array with the levels of the skills.
         */
        public $skill_levels = [];

        /**
         * Total experience required for the current level.
         */
        public $experience_level = 0;

        /**
         * Experience required to level up.
         */
        public $experience_level_up = 0;

        /**
         * Unit title.
         * If Homunculus,it will be it's name.
         * If awakened, it will be the awakened from name.
         * If unawakened, it will be <element> <name>.
         */
        public $title;


        /**
         * Constructor.
         *
         * Searches the database and retrieves the information about the
         * monster, populating it and it's items.
         *
         * @param SQLite3 $db Connection to the database.
         * @param int $id Monster identifier.
         * @param complete If false, query only monster and k_monster.
         */
        public function __construct($db, $id, $complete = true){
            global $path;
            parent::__construct($db);
            $s =
              "SELECT " .
              "  uid, " .
              "  id, " .
              "  building, " .
              "  unit, " .
              "  stars, " .
              "  level, " .
              "  hp, " .
              "  attack, " .
              "  defense, " .
              "  speed, " .
              "  crit_rate, " .
              "  crit_damage, " .
              "  resistance, " .
              "  accuracy, " .
              "  experience, " .
              "  exp_gained, " .
              "  exp_gain_rate, " .
              "  costume, " .
              "  attribute, " .
              "  source, " .
              "  create_time, " .
              "  homunculus, " .
              "  homunculus_name, " .
              "  lock " .
              "FROM unit " .
              "WHERE id = '$id'; ";
            $q = $this->db->query($s);
            $r = $q->fetchArray(SQLITE3_ASSOC);
            $this->uid = $r["uid"];
            $this->id = $r["id"];
            if (strlen($r["building"]) > 0){
                // TODO Entity $this->monster = new Building($this->db, $r["building"]);
            }
            if (strlen($r["unit"]) > 0){
                $this->unit = new K_Unit($this->db, $r["unit"], $complete);
            }
            $this->stars = $r["stars"];
            $this->level = $r["level"];
            $this->hp = $r["hp"];
            $this->attack = $r["attack"];
            $this->defense = $r["defense"];
            $this->speed = $r["speed"];
            $this->crit_rate = $r["crit_rate"];
            $this->crit_damage = $r["crit_damage"];
            $this->resistance = $r["resistance"];
            $this->accuracy = $r["accuracy"];
            $this->experience = $r["experience"];
            $this->exp_gained = $r["exp_gained"];
            $this->exp_gain_rate = $r["exp_gain_rate"];
            $this->costume = $r["costume"]; // TODO: Create entities?
            $this->attribute = $r["attribute"];
            $this->source = new K_Source($this->db, $r["source"]); // TODO: Instantiate?
            $this->create_time = date_create($r["create_time"]);
            $this->homunculus = $r["homunculus"];
            $this->homunculus_name = $r["homunculus_name"];
            #$this->avg_rune_efficiency = $r["avg_rune_efficiency"];
            #$this->fodder = $r["fodder"];
            #$this->in_storage = $r["in_storage"];
            #$this->ignore_for_fusion = $r["ignore_for_fusion"];
            #$this->priority = $r["priority"];
            #$this->notes = $r["notes"];
            if ($complete){
                $this->load_runes();
                $s =
                  "SELECT level " .
                  "FROM " .
                  "  unit_skill, " .
                  "  k_skill " .
                  "WHERE " .
                  "  k_skill.id = unit_skill.skill AND " .
                  "  unit = '$this->id' " .
                  "ORDER BY slot;";
                $q = $this->db->query($s);
                while ($r = $q->fetchArray(SQLITE3_ASSOC)){
                    array_push($this->skill_levels, $r["level"]);
                }
                $s =
                  "SELECT exp " .
                  "FROM k_experience " .
                  "WHERE " .
                  "  stars = $this->stars AND " .
                  "  level = $this->level;";
                $q = $this->db->query($s);
                $r = $q->fetchArray(SQLITE3_ASSOC);
                $this->experience_level = $r["exp"];
                $this->experience_level_up = $r["exp"] - $this->exp_gained;
            }
            if ($this->homunculus){
                $this->title = $this->homunculus_name;
            }
            else{
                $this->title = $this->unit->title;
            }
        }

        /**
         * Loads the information about the equiped runes. 
         * It is autoatically called at construction time if the
         * $complete parameter is true (by default). No point in calling it
         * twice.
         */
        public function load_runes(){
            $this->rune = [];
            $s =
              "SELECT id " .
              "FROM rune " .
              "WHERE assigned_to = '$this->id'; ";
            $q = $this->db->query($s);
            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
                array_push($this->rune, new Rune($this->db, $r["id"]));
            }
            foreach ($this->rune as $rune){
                $this->sum_rune_stat($rune->main_stat, $rune->main_stat_value);
                $this->sum_rune_stat($rune->innate_stat, $rune->innate_stat_value);
                $this->sum_rune_stat($rune->substat_1, $rune->substat_1_value + $rune->substat_1_grind);
                $this->sum_rune_stat($rune->substat_2, $rune->substat_2_value + $rune->substat_2_grind);
                $this->sum_rune_stat($rune->substat_3, $rune->substat_3_value + $rune->substat_3_grind);
                $this->sum_rune_stat($rune->substat_4, $rune->substat_4_value + $rune->substat_4_grind);
            }
            $this->rune_attack = ceil($this->rune_attack);
            $this->rune_defense = ceil($this->rune_defense);
            $this->rune_hp = ceil($this->rune_hp);
        }

        /**
         * Calculates the stat increase by a rune property.
         * 
         * @param string $stat Stat type.
         * @param int $value Stat increase value.
         */
        private function sum_rune_stat($stat, $value){
            global $RUNE_STAT;
            switch ($stat){
                case $RUNE_STAT["ATK"]:
                    $this->rune_attack += $value;
                    break;
                case $RUNE_STAT["DEF"]:
                    $this->rune_defense += $value;
                    break;
                case $RUNE_STAT["HP"]:
                    $this->rune_hp += $value;
                    break;
                case $RUNE_STAT["SPD"]:
                    $this->rune_speed += $value;
                    break;
                case $RUNE_STAT["CRR"]:
                    $this->rune_crit_rate += $value;
                    break;
                case $RUNE_STAT["CRD"]:
                    $this->rune_crit_damage += $value;
                    break;
                case $RUNE_STAT["ACC"]:
                    $this->rune_accuracy += $value;
                    break;
                case $RUNE_STAT["RES"]:
                    $this->rune_resistance += $value;
                    break;
                case $RUNE_STAT["ATK%"]:
                    $this->rune_attack += ($this->attack * $value / 100);
                    break;
                case $RUNE_STAT["DEF%"]:
                    $this->rune_defense += ($this->defense * $value / 100);
                    break;
                case $RUNE_STAT["HP%"]:
                    $this->rune_hp += ($this->hp * $value / 100);
                    break;
            }
        }
    }
?>
