<?php

/**
 * UpgradeModel
 *
 */
class UpgradeModel
{
    public static $upgradesTotal = 0;
    public static $upgradesSuccessful = 0;

    public static function runUpgrade()
    {
        $currentVersion = Config::getFromDB('MarketVersion');
        $prefix = Config::get('DB_PREFIX');

        switch ($currentVersion) {
            case 'BETA 0.9.5':
            case 'BETA 0.9.6':
            case 'BETA 0.9.7':
            case 'BETA 0.9.8':
            case 'BETA 0.9.8.1':
            case 'BETA 0.9.8.2':
            case 'BETA 0.9.8.3':
            case 'BETA 0.9.9':
            case 'BETA 0.10.0':
            case 'BETA 0.10.1':
            case 'BETA 0.11.0':
                self::alterTable("offers","add","zipcode","varchar",10,0,"null","null","cat3");
                self::alterTable("offers","change","price","decimal",20,8,"null","null","");
                if (!self::finishUpgrade('BETA 0.12.0')) {
                    break;
                }
            case 'BETA 0.12.0':
                if (!self::finishUpgrade('BETA 0.12.1')) {
                    break;
                }
            case 'BETA 0.12.1':
                if (!self::finishUpgrade('BETA 0.12.2')) {
                    break;
                }
            case 'BETA 0.12.2':
                if (!self::finishUpgrade('BETA 0.12.3')) {
                    break;
                }
            case 'BETA 0.12.3':
                if (!self::finishUpgrade('BETA 0.12.4')) {
                    break;
                }
            case 'BETA 0.12.4':
                InstallModel::insertSetting('MarketAdminEmail','value_text',Config::getFromDB('MarketContactEmail'));
                if (!self::finishUpgrade('BETA 0.12.5')) {
                    break;
                }
            case 'BETA 0.12.5':
                if (!self::finishUpgrade('BETA 0.12.6')) {
                    break;
                }
            case 'BETA 0.12.6':
                self::alterTable("users","add","user_approved","boolean",0,0,"notNull",1,"user_active");
                if (!self::finishUpgrade('BETA 0.13.0')) {
                    break;
                }
            case 'BETA 0.13.0':
                if (!self::finishUpgrade('BETA 0.13.1')) {
                    break;
                }
            case 'BETA 0.13.1':
                if (!self::finishUpgrade('BETA 0.13.2')) {
                    break;
                }
            case 'BETA 0.13.2':
                if (!self::finishUpgrade('BETA 0.13.3')) {
                    break;
                }
            case 'BETA 0.13.3':
                InstallModel::insertSetting('MarketDetailLink','value_int',0);
                InstallModel::insertSetting('MarketDetailLinkText','value_text',AdminText::get('DEFAULT_DETAIL_LINK_TEXT'));
                InstallModel::insertSetting('MarketContactLink','value_int',0);
                InstallModel::insertSetting('MarketContactLinkText','value_text',AdminText::get('DEFAULT_CONTACT_LINK_TEXT'));
                if (!self::finishUpgrade('BETA 0.13.4')) {
                    break;
                }
            case 'BETA 0.13.4':
                self::alterTable("profiles","add","other_featured","boolean",0,0,"notNull",0,"admin_featured");
                if (!self::finishUpgrade('BETA 0.13.5')) {
                    break;
                }
            case 'BETA 0.13.5':
                if (!self::finishUpgrade('BETA 0.14.0')) {
                    break;
                }
            case 'BETA 0.14.0':
                if (!self::finishUpgrade('BETA 0.15.0')) {
                    break;
                }
            case 'BETA 0.15.0':
                self::alterTable("users","drop_index","user_email",0,0,0,0,0,0);
                if (!self::finishUpgrade('BETA 0.16.0')) {
                    break;
                }
            case 'BETA 0.16.0':
        }
    }

    private static function alterTable($table,$type,$columnName,$dataType,$numPrec,$numScale,$default,$defaultValue,$after = '')
    {
        self::$upgradesTotal++;
        $prefix = Config::get('DB_PREFIX');
        $database = DatabaseFactory::getFactory()->getConnection();

        if (self::checkTableUpgradeStatus($table,$type,$columnName,$dataType,$numPrec,$numScale)) {
            self::$upgradesSuccessful++;
            return true;
        }

        switch ($type) {
            case 'add':
                $sql = "ALTER TABLE ".$prefix.$table."
                        ADD ".$columnName." ".self::getDataType($dataType,$numPrec,$numScale)." ".self::getDefault($default,$defaultValue)."
                        AFTER ".$after;
                break;
            case 'change':
                $sql = "ALTER TABLE ".$prefix.$table."
                        CHANGE ".$columnName." ".$columnName." ".self::getDataType($dataType,$numPrec,$numScale)." ".self::getDefault($default,$defaultValue);
                break;
            case 'drop_index':
                $sql = "ALTER TABLE ".$prefix.$table." DROP INDEX ".$columnName;
        }
        $database->query($sql);

        if (self::checkTableUpgradeStatus($table,$type,$columnName,$dataType,$numPrec,$numScale)) {
            self::$upgradesSuccessful++;
        }
    }

    private static function checkTableUpgradeStatus($table,$type,$columnName,$dataType = '',$numPrec = 0,$numScale = 0)
    {
        $prefix = Config::get('DB_PREFIX');
        $DBName = Config::get('DB_NAME');
        $tableName = $prefix.$table;
        $database = DatabaseFactory::getFactory()->getConnection();
        switch ($type) {
            case 'add':
                $sql = "SELECT *
                        FROM information_schema.COLUMNS
                        WHERE TABLE_SCHEMA = :table_schema
                          AND TABLE_NAME = :table_name
                          AND COLUMN_NAME = :column_name
                        LIMIT 1";
                $query = $database->prepare($sql);
                $query->bindParam(':table_schema',  $DBName,        PDO::PARAM_STR);
                $query->bindParam(':table_name',    $tableName,     PDO::PARAM_STR);
                $query->bindParam(':column_name',   $columnName,    PDO::PARAM_STR);
                if ($query->execute() && $query->rowCount() == 1) {
                    return true;
                } else {
                    return false;
                }
                break;
            case 'change':
                $sql = "SELECT *
                        FROM information_schema.COLUMNS
                        WHERE TABLE_SCHEMA = :table_schema
                          AND TABLE_NAME = :table_name
                          AND COLUMN_NAME = :column_name
                          AND DATA_TYPE = :data_type
                          AND NUMERIC_PRECISION = :num_prec
                          AND NUMERIC_SCALE = :num_scale
                        LIMIT 1";
                $query = $database->prepare($sql);
                $query->bindParam(':table_schema',  $DBName,        PDO::PARAM_STR);
                $query->bindParam(':table_name',    $tableName,     PDO::PARAM_STR);
                $query->bindParam(':column_name',   $columnName,    PDO::PARAM_STR);
                $query->bindParam(':data_type',     $dataType,      PDO::PARAM_STR);
                $query->bindParam(':num_prec',      $numPrec,       PDO::PARAM_INT);
                $query->bindParam(':num_scale',     $numScale,      PDO::PARAM_INT);
                if ($query->execute() && $query->rowCount() == 1) {
                    return true;
                } else {
                    return false;
                }
                break;
            case 'drop_index':
                $sql = "SELECT DISTINCT CONSTRAINT_NAME
                        FROM information_schema.TABLE_CONSTRAINTS
                        WHERE table_name = :table_name
                          AND constraint_type = 'UNIQUE'
                          AND CONSTRAINT_NAME = :column_name
                        LIMIT 1";
                $query = $database->prepare($sql);
                $query->bindParam(':table_name',    $tableName,     PDO::PARAM_STR);
                $query->bindParam(':column_name',   $columnName,    PDO::PARAM_STR);
                if ($query->execute() && $query->rowCount() == 0) {
                    return true;
                } else {
                    return false;
                }
        }
    }

    private static function getDataType($type,$numPrec,$numScale = 0)
    {
        switch ($type) {
            case 'varchar':
                return "VARCHAR ( ".$numPrec." )";
                break;
            case 'decimal':
                return "DECIMAL ( ".$numPrec.",".$numScale." )";
                break;
            case 'boolean':
                return "TINYINT (1)";
                break;
            case 'int':
                return "INT (".$numPrec.")";
                break;
        }
    }

    private static function getDefault($type, $default = 0)
    {
        switch ($type) {
            case 'null':
                return "NULL DEFAULT NULL";
                break;
            case 'notNull':
                return "NOT NULL DEFAULT ".$default;
                break;
        }
    }

    private static function finishUpgrade($version)
    {
        if (self::$upgradesTotal == self::$upgradesSuccessful)
        {
            AdminModel::updateSettings('MarketVersion','value_text',$version);
            Session::add('feedback_positive',
                         PA::filter(AdminText::get('PLATFORM_UPGRADE_SUCCESSFUL'),$version));
            return true;
        } else {
            Session::add('feedback_negative',
                         PA::filter(AdminText::get('PLATFORM_UPGRADE_UNSUCCESSFUL'),$version));
            return false;
        }
    }
}
