<?php

Class ChangeClass {

    function __construct() {
		
        # Get Classes
        # ---------------
		# Database Class
		$this->dB = Connection::Database('MuOnline');

        # Load Character Class
        $this->Character = new Character();

        # Load Common Class
        $this->common = new common();

        # Load Config
        $config = loadConfigurations('changeclass');
        if(!is_array($config)) throw new Exception(lang('error_98'));
        $this->_configs = $config;

		$classData = custom('character_class');
		if(!is_array($classData)) throw new Exception(lang('error_108'));
		$this->_classData = $classData;

        $this->iClass_First                =   array(0, 16, 32, 48, 64, 80, 96);
        $this->iClass_Second               =   array(1, 17, 33, 81);
        $this->iClass_Third                =   array(2, 18, 34, 50, 66, 82, 98);

        $ActivesClass = array(
            array($this->_configs['first_class'] == 1, 0, 'Dark Wizard'),
            array($this->_configs['second_class']  == 1, 1, 'Soul Master'),
            array($this->_configs['third_class']  == 1, 2, 'Grand Master'),
            array($this->_configs['first_class']  == 1, 16, 'Dark Knight'),
            array($this->_configs['second_class']  == 1, 17, 'Blade Knight'),
            array($this->_configs['third_class']  == 1, 18, 'Blade Master'),
            array($this->_configs['first_class']  == 1, 32, 'Fairy Elf'),
            array($this->_configs['second_class']  == 1, 33, 'Muse Elf'),
            array($this->_configs['third_class']  == 1, 34, 'High Elf'),
            array($this->_configs['first_class']  == 1, 48, 'Magic Gladiator'),
            array($this->_configs['third_class']  == 1, 50, 'Duel Master'),
            array($this->_configs['first_class']  == 1, 64, 'Dark Lord'),
            array($this->_configs['third_class']  == 1, 66, 'Lord Emperor'),
            array($this->_configs['first_class']  == 1, 80, 'Summoner'),
            array($this->_configs['second_class']  == 1, 81, 'Bloody Summoner'),
            array($this->_configs['third_class']  == 1, 82, 'Dimension Master'),
            array($this->_configs['first_class']  == 1, 96, 'Rage Fighter'),
            array($this->_configs['third_class']  == 1, 98, 'Fist Master'),
        );
    
        $this->iChange_Class = array();

        foreach ($ActivesClass as $ActiveClass) {
            if ($ActiveClass[0]) {
                $this->iChange_Class[$ActiveClass[1]] = $ActiveClass[2];
            }
        }
    }

    public function GetClassChar($Character_Name){
        $ClassChar = $this->dB->query_fetch_single("SELECT Class FROM Character WHERE Name = ?", array($Character_Name));
        if(!is_array($ClassChar)) return;
        return $ClassChar;
    }

    public function GetStatsChar($Character_Class){
        $StatsChar = $this->dB->query_fetch_single("SELECT * FROM DefaultClassType WHERE Class = ?", array($Character_Class));
        if(!is_array($StatsChar)) return;
        return $StatsChar;
    }

    public function GetGroupClass($Character_Class){
        switch($Character_Class){
            case 0: $GroupClass = 0; break;        // SM
            case 1: $GroupClass = 0; break;        // SM
            case 2: $GroupClass = 0; break;        // SM
            case 3: $GroupClass = 0; break;        // SM
            case 16: $GroupClass = 16; break;      // BK
            case 17: $GroupClass = 16; break;      // BK
            case 18: $GroupClass = 16; break;      // BK
            case 19: $GroupClass = 16; break;      // BK
            case 32: $GroupClass = 32; break;      // ELF
            case 33: $GroupClass = 32; break;      // ELF
            case 34: $GroupClass = 32; break;      // ELF
            case 35: $GroupClass = 32; break;      // ELF
            case 48: $GroupClass = 48; break;      // MG
            case 49: $GroupClass = 48; break;      // MG
            case 50: $GroupClass = 48; break;      // MG
            case 64: $GroupClass = 64; break;      // DL
            case 65: $GroupClass = 64; break;      // DL
            case 66: $GroupClass = 64; break;      // DL
            case 80: $GroupClass = 80; break;      // SUM
            case 81: $GroupClass = 80; break;      // SUM
            case 82: $GroupClass = 80; break;      // SUM
            case 83: $GroupClass = 80; break;      // SUM
            case 96: $GroupClass = 96; break;      // RF
            case 97: $GroupClass = 96; break;      // RF
            case 98: $GroupClass = 96; break;      // RF
            default:
                $GroupClass = 0;
        }
        return $GroupClass;
    }
    
    public function GetPriceClass($OldClass, $NewClass){
        $ClassMaps = [
            0 => 'dw',
            16 => 'dk',
            32 => 'elf',
            48 => 'mg',
            64 => 'dl',
            80 => 'sum',
            96 => 'rf'
        ];
    
        $OldGroupClass = $this->GetGroupClass($OldClass);
        $NewGroupClass = $this->GetGroupClass($NewClass);
    
        $OldClassName = $ClassMaps[$OldGroupClass] ?? false;
        $NewClassName = $ClassMaps[$NewGroupClass] ?? false;
    
        if($OldClassName === false || $NewClassName === false)  throw new Exception("<b>[ Change Class ]</b> This class was not found.");
    
        $priceKey = "{$OldClassName}_to_{$NewClassName}";
    
        if (isset($this->_configs[$priceKey])) {
            $PriceClass = $this->_configs[$priceKey];
        } else {
            throw new Exception("<b>[ Change Class ]</b> Could not generate price.");
        }
    
        return $PriceClass;
    }    

    public function GetCoins($Usuario){
        $result = $this->dB->query_fetch_single("SELECT * FROM ".$this->_configs['tabla_coins']." WHERE ".$this->_configs['columna_tabla_coins']."='".$Usuario."'");
        if(!is_array($result)) return;
        return $result;
    }

    public function SubstractCoins($Price,$Username){
        $CoinDiscount    =   "UPDATE ".$this->_configs['tabla_coins']." ";
        $CoinDiscount   .=   "SET ".$this->_configs['moneda']." = ".$this->_configs['moneda']."-".$Price." ";
        $CoinDiscount   .=   "WHERE ".$this->_configs['columna_tabla_coins']." = '".$Username."' ";

        $result     =   $this->dB->query_fetch_single($CoinDiscount);  
        return $result;
    }

    public function Verificaciones($Username,$Character,$NewClass){
        try{
            if(!check_value($Username)) throw new Exception("<b><b>[ Change Class ]</b></b> An unexpected error has occurred, please try again.");
            if(!check_value($Character)) throw new Exception("<b><b>[ Change Class ]</b></b> An unexpected error has occurred, please try again.");
            if(!check_value($NewClass)) throw new Exception("<b><b>[ Change Class ]</b></b> An unexpected error has occurred, please try again.");
            if(!Validator::UsernameLength($Username)) throw new Exception("<b><b>[ Change Class ]</b></b> An unexpected error has occurred, please try again.");

            $OldClassChar  = $this->GetClassChar($Character);
            $OldGroupClass = $this->GetGroupClass($OldClassChar['Class']);
            $NewGroupClass = $this->GetGroupClass($NewClass);
            $characterData = $this->Character->characterData($Character);

            if($this->_configs['first_class'] == 0 && in_array($NewClass, $this->iClass_First)) throw new Exception('<b>[ Change Class ]</b> This <b>Class</b> is disabled.');
            if($this->_configs['second_class'] == 0 && in_array($NewClass, $this->iClass_Second)) throw new Exception('<b>[ Change Class ]</b> Esta <b>Clase</b> esta deshabilitada.');
            if($this->_configs['third_class'] == 0 && in_array($NewClass, $this->iClass_Third)) throw new Exception('<b>[ Change Class ]</b> Esta <b>Clase</b> esta deshabilitada.');
            if(!array_key_exists($NewClass, $this->iChange_Class)) throw new Exception('<b>[ Change Class ]</b> This <b>Class</b> does not exist.');
            if($OldGroupClass == $NewGroupClass) throw new Exception('<b>[ Change Class ]</b> You have selected the <b>Class</b> that you are already.');
            if($this->_configs['allowfirstclass'] == 0) { if(in_array($OldClassChar['Class'], $this->iClass_First) && !in_array($NewClass, $this->iClass_First)) throw new Exception('<b>[ Change Class ]</b> You can only move to <b>Classes</b> of the same <b>Evolution</b> level as your class.'); }
            if($this->_configs['allowsecondclass'] == 0) { if(in_array($OldClassChar['Class'], $this->iClass_Second) && !in_array($NewClass, $this->iClass_Second)) throw new Exception('<b>[ Change Class ]</b> You can only move to <b>Classes</b> of the same <b>Evolution</b> level as your class.'); }
            if($this->_configs['allowthirdclass'] == 0) { if(in_array($OldClassChar['Class'], $this->iClass_Third) && !in_array($NewClass, $this->iClass_Third)) throw new Exception('<b>[ Change Class ]</b> You can only move to <b>Classes</b> of the same <b>Evolution</b> level as your class.'); }

            if($characterData[_CLMN_CHR_LVL_] < $this->_configs['minimum_level']) throw new Exception('<b>[ Change Class ]</b> The minimum Level required is <b>'.$this->_configs['minimum_level'].'</b>.');
            if($characterData[_CLMN_CHR_RSTS_] < $this->_configs['minimum_resets']) throw new Exception('<b>[ Change Class ]</b> The minimum Reset required is <b>'.$this->_configs['minimum_resets'].'</b>.');
            if($characterData[_CLMN_CHR_GRSTS_] < $this->_configs['minimum_mresets']) throw new Exception('<b>[ Change Class ]</b> The minimum Master Reset required is <b>'.$this->_configs['minimum_resets'].'</b>.');

            $this->SetNewClass($Username,$Character,$OldClassChar['Class'],$NewClass);

        }catch(Exception $ex) {
            message('error', $ex->getMessage());
        }
    }

    public function SetNewClass($Username,$Character,$OldClass,$NewClass){
        try{
            date_default_timezone_set('America\Argentina\Tucuman');
            $Fecha              =   date('Y-m-d H:i:s',time());
            $Price              =   $this->GetPriceClass($OldClass, $NewClass);
            $Coins              =   $this->GetCoins($Username);
            if(!$this->common->accountOnline($Username))
            {
                if($Coins[$this->_configs['moneda']] >= $Price )
                {
                    # Query Character
                    $OldGroupClass              =   $this->GetGroupClass($OldClass); 
                    $NewGroupClass              =   $this->GetGroupClass($NewClass); 
                    $GetStatsDef                =   $this->GetStatsChar($NewGroupClass);
                    $GetStatsDefOld             =   $this->GetStatsChar($OldGroupClass);
                    $characterData              =   $this->Character->characterData($Character);
                    $characterMData             =   $this->Character->getMasterLevelInfo($Character);
                    $Stats                      =   $characterData[_CLMN_CHR_STAT_STR_]+$characterData[_CLMN_CHR_STAT_AGI_]+$characterData[_CLMN_CHR_STAT_VIT_]+$characterData[_CLMN_CHR_STAT_ENE_]+$characterData[_CLMN_CHR_STAT_CMD_];
                    $StatsDef                   =   $GetStatsDefOld[_CLMN_CHR_STAT_STR_]+$GetStatsDefOld[_CLMN_CHR_STAT_AGI_]+$GetStatsDefOld[_CLMN_CHR_STAT_VIT_]+$GetStatsDefOld[_CLMN_CHR_STAT_ENE_]+$GetStatsDefOld[_CLMN_CHR_STAT_CMD_];
                    $NewLevelPoints             =   $Stats-$StatsDef;

                    $SetCharRec         =   "UPDATE "._TBL_CHR_." SET ";
                    $SetCharRec        .=   ""._CLMN_CHR_MAGIC_L_." = NULL, ";
                    $SetCharRec        .=   ""._CLMN_CHR_STAT_STR_." = ".$GetStatsDef[_CLMN_CHR_STAT_STR_].", ";
                    $SetCharRec        .=   ""._CLMN_CHR_STAT_AGI_." = ".$GetStatsDef[_CLMN_CHR_STAT_AGI_].", ";
                    $SetCharRec        .=   ""._CLMN_CHR_STAT_VIT_." = ".$GetStatsDef[_CLMN_CHR_STAT_VIT_].", ";
                    $SetCharRec        .=   ""._CLMN_CHR_STAT_ENE_." = ".$GetStatsDef[_CLMN_CHR_STAT_ENE_].", ";
                    $SetCharRec        .=   ""._CLMN_CHR_STAT_CMD_." = ".$GetStatsDef[_CLMN_CHR_STAT_CMD_].", ";
                    $SetCharRec        .=   ""._CLMN_CHR_LVLUP_POINT_." = "._CLMN_CHR_LVLUP_POINT_."+".$NewLevelPoints.", ";
                    $SetCharRec        .=   ""._CLMN_CHR_CLASS_." = ".$NewClass.", ";
                    if(in_array($NewClass, $this->iClass_First))            $SetCharRec .=   ""._CLMN_CHR_QUEST_." = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ";
                    else if(in_array($NewClass, $this->iClass_Second))      $SetCharRec .=   ""._CLMN_CHR_QUEST_." = 0xAA00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ";
                    else if(in_array($NewClass, $this->iClass_Third))       $SetCharRec .=   ""._CLMN_CHR_QUEST_." = 0xAAEAFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ";
                    $SetCharRec        .=   "WHERE "._CLMN_CHR_NAME_."='".$Character."'  ";
                    $CharRecResult      =   $this->dB->query_fetch_single($SetCharRec);

                    # Query Master
                    if(in_array($NewClass, $this->iClass_Third)){
                        $PointsForML        =   $this->_configs['points_for_ml'];
                        $MasterL            =   $characterMData[_CLMN_ML_LVL_];
                        $NewMP              =   ($MasterL*$PointsForML);
                        $SetMasterRec         =   "UPDATE "._TBL_MASTERLVL_." SET ";
                        $SetMasterRec        .=   ""._CLMN_ML_POINT_." = ".$NewMP.", ";
                        $SetMasterRec        .=   ""._CLMN_ML_SKILL_." = NULL ";                    
                        $SetMasterRec        .=   "WHERE "._CLMN_ML_NAME_." = '".$Character."'  ";
                        $MasterRecResult      =   $this->dB->query_fetch_single($SetMasterRec);
                    }

                    $this->SubstractCoins($Price,$Username);
                    message('success', '<b>[ Change Class ]</b> You have changed to class <b>'.$this->_classData[$NewClass][0].'</b> successfully!.');
                    message('error', '<b>[ Change Class ]</b> You have been discounted <b>'.number_format($Price,0,',','.').'</b> from your <b>'.$this->_configs['moneda_v'].'</b>.');
                    $this->InsertLOGS($Username, $Character, $OldClass, $NewClass, $Price, $Fecha);
                }else{
                    message('error', '<b>[ Change Class ]</b> You don\'t have enough <b>'.$this->_configs['moneda_v'].'</b>. You need to have <b>'.number_format($Price,0,',','.').' '.$this->_configs['moneda_v'].'</b> to switch to this class.');
                }
            } else{
                message('error', '<b>[ Change Class ]</b> La cuenta debe estar <b>desconectada del juego</b> para cambiar de <b>Clase</b>.');
            }

        }catch(Exception $ex) {
            message('error', $ex->getMessage());
        }
    }

    public function InsertLOGS($Usuario, $Character, $OldClass, $NewClass, $Precio, $Fecha){                   
        $Query      =    "INSERT INTO WEBENGINE_CHANGE_CLASS_LOGS (usuario, character, oldclass, newclass, precio, fecha) ";
        $Query      .=   "VALUES ('".$Usuario."', '".$Character."', ".$OldClass.",".$NewClass.", ".$Precio.", '".$Fecha."')";

        $InsertLog  = $this->dB->query_fetch_single($Query);
    }

    public function GetLogs()
    {
        $result = $this->dB->query_fetch("SELECT * FROM WEBENGINE_CHANGE_CLASS_LOGS ORDER BY id DESC");
        if(!is_array($result)) return;
        return $result;
    }

}