 <?php
    /**
     * Upgradeable runes report page file.
     *
     * Provides a class with all the properties and methods to display the page.
     *
     * @category Page
     */

    /**
     * Require dependent files if not present.
     */
    require_once(PATH::PAGE . "Page.php");
    require_once(PATH::ENTITY . "Unit.php");
    require_once(PATH::ENTITY . "Rune.php");
    require_once(PATH::ENTITY . "Rune_Craft.php");

    /**
     * Upgradeable runes report page model.
     *
     * @category Page
     */
    class Report_Runecraft_Page extends Page{

        /**
         * @var mixed[] List of available upgrades.
         *
         * Can be described as:
         * $upgrades = [
         *   [
         *     unit (Unit),
         *     upgrade = [
         *       [
         *         rune (Rune),
         *         craft = [(Rune_Craft)]
         *       ]
         *     ]
         *   ]
         * ]
         */
        public $upgrades = [];

        /**
         * Constructor.
         *
         * Retrieves the data and initializes the variables.
         *
         * @param resource $db Connection to the database.
         */
        public function __construct($db){
            parent::__construct($db);
            $this->view = PATH::VIEW . "report_runecraft.php";
            $this->parse_filters();
            $s = $this->build_query();
            $q = $this->db->query($s);
            $prev_monster = "";
            $prev_rune = "";
            $upgrade = null;
            $rupgrade = null;
            while ($r = $q->fetchArray(SQLITE3_ASSOC)){
                if ($r["unit"] != $prev_monster){
                    if ($prev_rune != ""){
                        array_push($upgrade["upgrade"], $rupgrade);
                    }
                    if ($prev_monster != ""){
                        array_push($this->upgrades, $upgrade);
                    }
                    $prev_monster = $r["unit"];
                    $prev_rune = "";
                    $upgrade = [
                        "unit" => new Unit($this->db, $r["unit"]),
                        "upgrade" => [],
                    ];
                    $rupgrade = [
                        "rune" => new Rune($this->db, $r["rune"]),
                        "craft" => [],
                    ];
                }
                if ($r["rune"] != $prev_rune){
                    if ($prev_rune != ""){
                        array_push($upgrade["upgrade"], $rupgrade);
                    }
                    $prev_rune = $r["rune"];
                    $rupgrade = [
                        "rune" => new Rune($this->db, $r["rune"]),
                        "craft" => [],
                    ];
                }
                $rune_craft = new Rune_craft($this->db, $r["craft"]);
                array_push($rupgrade["craft"], $rune_craft);
            }
            // Last entries
            array_push($upgrade["upgrade"], $rupgrade);
            array_push($this->upgrades, $upgrade);
            $this->title = "Rune craft - SWDB";
            $this->description = "Find runes that can be upgraded via crafting.";
            $this->canonical = URL::BASE . "report/runecraft/";
        }

        /**
         * Parses the filters passed in the request and sets $filters.
         * Filters must be in $_GET, nd the available ones are max_stars (1-6),
         * min_stars (1-6) and in_storage (on/off).
         */
        private function parse_filters(){
            $this->filters = FILTER::RUNECRAFT;
            // Monster
            if (isset($_GET["monster_min_stars"]) && intval($_GET["monster_min_stars"]) > 0 && intval($_GET["monster_min_stars"]) < 7){
                $this->filters["MONSTER_MIN_STARS"] = $_GET["monster_min_stars"];
            }
            if (isset($_GET["monster_max_stars"]) && intval($_GET["monster_max_stars"]) > 0 && intval($_GET["monster_max_stars"]) < 7){
                $this->filters["MONSTER_MAX_STARS"] = $_GET["monster_max_stars"];
            }
            if (isset($_GET["monster_in_storage"]) && $_GET["monster_in_storage"] == "on"){
                $this->filters["MONSTER_IN_STORAGE"] = true;
            }
            else{
                $this->filters["MONSTER_IN_STORAGE"] = false;
            }
            if (isset($_GET["monster_name"]) && strlen($_GET["monster_name"]) > 0){
                $this->filters["MONSTER_NAME"] = SQLite3::escapeString($_GET["monster_name"]);
            }
            // Runes
            if (isset($_GET["rune_min_stars"]) && intval($_GET["rune_min_stars"]) > 0 && intval($_GET["rune_min_stars"]) < 7){
                $this->filters["RUNE_MIN_STARS"] = $_GET["rune_min_stars"];
            }
            if (isset($_GET["rune_max_stars"]) && intval($_GET["rune_max_stars"]) > 0 && intval($_GET["rune_max_stars"]) < 7){
                $this->filters["RUNE_MAX_STARS"] = $_GET["rune_max_stars"];
            }
            if (isset($_GET["rune_min_level"]) && intval($_GET["rune_min_level"]) >= 0 && intval($_GET["rune_min_level"]) <= 15){
                $this->filters["RUNE_MIN_LEVEL"] = $_GET["rune_min_level"];
            }
            if (isset($_GET["rune_max_level"]) && intval($_GET["rune_max_level"]) >= 0 && intval($_GET["rune_max_level"]) <= 15){
                $this->filters["RUNE_MAX_LEVEL"] = $_GET["rune_max_level"];
            }
            if (isset($_GET["rune_min_quality"]) && intval($_GET["rune_min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_min_quality"]) <= QUALITY_ID::LEGEND){
                $this->filters["RUNE_MIN_QUALITY"] = $_GET["rune_min_quality"];
            }
            if (isset($_GET["rune_max_quality"]) && intval($_GET["rune_max_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_max_quality"]) <= QUALITY_ID::LEGEND){
                $this->filters["RUNE_MAX_QUALITY"] = $_GET["rune_max_quality"];
            }
            if (isset($_GET["rune_min_original_quality"]) && intval($_GET["rune_min_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_min_original_quality"]) <= QUALITY_ID::LEGEND){
                $this->filters["RUNE_MIN_ORIGINAL_QUALITY"] = $_GET["rune_min_original_quality"];
            }
            if (isset($_GET["rune_max_original_quality"]) && intval($_GET["rune_max_original_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["rune_max_original_quality"]) <= QUALITY_ID::LEGEND){
                $this->filters["RUNE_MAX_ORIGINAL_QUALITY"] = $_GET["rune_max_original_quality"];
            }
            if (isset($_GET["rune_min_efficiency"]) && intval($_GET["rune_min_efficiency"]) >= 0 && intval($_GET["rune_min_efficiency"]) <= 100){
                $this->filters["RUNE_MIN_EFFICIENCY"] = $_GET["rune_min_efficiency"];
            }
            if (isset($_GET["rune_max_efficiency"]) && intval($_GET["rune_max_efficiency"]) >= 0 && intval($_GET["rune_max_efficiency"]) <= 100){
                $this->filters["RUNE_MAX_EFFICIENCY"] = $_GET["rune_max_efficiency"];
            }
            if (isset($_GET["rune_min_max_efficiency"]) && intval($_GET["rune_min_max_efficiency"]) >= 0 && intval($_GET["rune_min_max_efficiency"]) <= 100){
                $this->filters["RUNE_MIN_MAX_EFFICIENCY"] = $_GET["rune_min_max_efficiency"];
            }
            if (isset($_GET["rune_max_max_efficiency"]) && intval($_GET["rune_max_max_efficiency"]) >= 0 && intval($_GET["rune_max_max_efficiency"]) <= 100){
                $this->filters["RUNE_MAX_MAX_EFFICIENCY"] = $_GET["rune_max_max_efficiency"];
            }
            if (isset($_GET["rune_slot"])){
                $slots = $_GET["rune_slot"];
                foreach ($slots as $slot){
                    if (intval($slot) >= 1 && intval($slot) < 7){
                        array_push($this->filters["RUNE_SLOT"], intval($slot));
                    }
                }
            }
            // Grindstones
            if (isset($_GET["grind_min_quality"]) && intval($_GET["grind_min_quality"]) >= QUALITY_ID::NORMAL && intval($_GET["grind_min_quality"]) < QUALITY_ID::LEGEND){
                $this->filters["GRIND_MIN_QUALITY"] = $_GET["grind_min_quality"];
            }
            if (isset($_GET["grind_stat"])){
                $stats = $_GET["grind_stat"];
                $this->filters["GRIND_STAT"] = [];
                foreach ($stats as $stat){
                    array_push($this->filters["GRIND_STAT"], intval($stat));
                }
            }
            if (isset($_GET["gem_stat_from"])){
                $stats = $_GET["gem_stat_from"];
                $this->filters["GEM_STAT_FROM"] = [];
                foreach ($stats as $stat){
                    array_push($this->filters["GEM_STAT_FROM"], intval($stat));
                }
            }
            if (isset($_GET["gem_stat_to"])){
                $stats = $_GET["gem_stat_to"];
                $this->filters["GEM_STAT_TO"] = [];
                foreach ($stats as $stat){
                    array_push($this->filters["GEM_STAT_TO"], intval($stat));
                }
            }
            return;
        }

        /**
         * Builds the query for the page, using the providded or default filters.
         *
         * @return string The query to be executed.
         * @global int Player ID.
         */
        private function build_query(){
            global $UID;
            $s = "
                SELECT
                  unit.id AS unit,
                  rune.id AS rune,
                  rune_craft.id AS craft
                FROM
                  unit,
                  k_unit,
                  rune,
                  rune_craft,
                  k_rune_craft_type
                WHERE
                  unit.uid = '$UID' AND
                  rune.uid = '$UID' AND
                  rune_craft.uid = '$UID' AND
                  unit.id = rune.assigned_to AND
                  unit.unit = k_unit.id AND
                  rune_craft.type = k_rune_craft_type.id AND
                  unit.stars >= " . $this->filters["RUNE_MIN_STARS"] . " AND
                  unit.stars <= " . $this->filters["RUNE_MAX_STARS"] . " AND
                  -- RUNE FILTERS
                  rune.quality >= " . $this->filters["RUNE_MIN_QUALITY"] . " AND
                  rune.quality <= " . $this->filters["RUNE_MAX_QUALITY"] . " AND
                  rune.level >= " . $this->filters["RUNE_MIN_LEVEL"] . " AND
                  rune.level <= " . $this->filters["RUNE_MAX_LEVEL"] . " AND
                  rune.stars >= " . $this->filters["RUNE_MIN_STARS"] . " AND
                  rune.stars <= " . $this->filters["RUNE_MAX_STARS"] . " AND
                  rune.original_quality >= " . $this->filters["RUNE_MIN_ORIGINAL_QUALITY"] . " AND
                  rune.original_quality <= " . $this->filters["RUNE_MAX_ORIGINAL_QUALITY"] . " AND
                  rune.efficiency >= " . $this->filters["RUNE_MIN_EFFICIENCY"] . " AND
                  rune.efficiency <= " . $this->filters["RUNE_MAX_EFFICIENCY"] . " AND
                  rune.max_efficiency >= " . $this->filters["RUNE_MIN_MAX_EFFICIENCY"] . " AND
                  rune.max_efficiency <= " . $this->filters["RUNE_MAX_MAX_EFFICIENCY"] . " AND
                  (
                    rune.type = rune_craft.rune OR 
                    k_rune_craft_type.inmemorial = 1
                  ) AND
                  k_rune_craft_type.ancient = rune.ancient AND
                ";
            if (strlen($this->filters["MONSTER_NAME"]) > 0){
                $s = $s . " upper(k_unit.name) LIKE = upper('%" . $this->filters["MONSTER_NAME"] . "%') AND ";
            }
            if (!$this->filters["MONSTER_IN_STORAGE"]){
                $s = $s . " unit.building <> " . BUILDING_ID::MONSTER_STORAGE . " AND ";
            }
            if (count($this->filters["RUNE_SLOT"]) > 0){
                $s = $s . " rune.slot IN ( ";
                foreach($this->filters["RUNE_SLOT"] as $t){
                    $s = $s . "$t, ";
                }
                $s = $s . "-1) AND ";
            }
            $s .= "
                rune_craft.stat <> rune.main_stat AND
                rune_craft.stat <> rune.innate_stat AND
                  (
                    k_rune_craft_type.gem = 1 AND
                    (
                      -- GEM FILTERS
                      rune_craft.quality >= " . $this->filters["GEM_MIN_QUALITY"] . " AND
            ";
            if (count($this->filters["GEM_STAT_FROM"]) > 0){
                $in = "(";
                foreach($this->filters["GEM_STAT_FROM"] as $t){
                    $in = $in . "$t, ";
                }
                $in = $in . "-1)";
                $s .= " (rune.substat_1 IN $in OR rune.substat_2 IN $in OR rune.substat_3 IN $in OR rune.substat_4 IN $in) AND ";
            }
            if (count($this->filters["GEM_STAT_TO"]) > 0){
                $in = "(";
                foreach($this->filters["GEM_STAT_TO"] as $t){
                    $in = $in . "$t, ";
                }
                $in = $in . "-1)";
                $s .= " rune_craft.stat IN $in AND ";
            }
            $s .= "
                      (
                        rune_craft.stat <> rune.substat_1 AND
                        rune_craft.stat <> rune.substat_2 AND
                        rune_craft.stat <> rune.substat_3 AND
                        rune_craft.stat <> rune.substat_4
                      )
                    )
                  ) |
                  (
                    k_rune_craft_type.gem = 0 AND
                    (
                      -- GRINDSTONE FILTERS
            ";
            if (count($this->filters["GRIND_STAT"]) > 0){
                $in = "(";
                foreach($this->filters["GRIND_STAT"] as $t){
                    $in = $in . "$t, ";
                }
                $in = $in . "-1)";
                $s .= " rune_craft.stat IN $in AND ";
            }
            $s .= "
                      rune_craft.quality >= " . $this->filters["GRIND_MIN_QUALITY"] . " AND
                      (
                        (
                          rune_craft.stat = rune.substat_1 AND
                          rune_craft.stat <> rune.substat_2 AND
                          rune_craft.stat <> rune.substat_3 AND
                          rune_craft.stat <> rune.substat_4
                        ) OR
                        (
                          rune_craft.stat <> rune.substat_1 AND
                          rune_craft.stat = rune.substat_2 AND
                          rune_craft.stat <> rune.substat_3 AND
                          rune_craft.stat <> rune.substat_4
                        ) OR
                        (
                          rune_craft.stat <> rune.substat_1 AND
                          rune_craft.stat <> rune.substat_2 AND
                          rune_craft.stat = rune.substat_3 AND
                          rune_craft.stat <> rune.substat_4
                        ) OR
                        (
                          rune_craft.stat <> rune.substat_1 AND
                          rune_craft.stat <> rune.substat_2 AND
                          rune_craft.stat <> rune.substat_3 AND
                          rune_craft.stat = rune.substat_4
                        )
                      )
                    )
                  )
                ";
            $s .= "
                ORDER BY
                  unit.stars DESC,
                  unit.level DESC,
                  unit.id,
                  rune.stars DESC,
                  rune.original_quality DESC,
                  rune.level DESC,
                  rune.id, 
                  rune.slot, 
                  rune_craft.quality DESC,
                  rune_craft.stat DESC;
                ";
            return $s;
        }
    }
?>
