<?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',Text::get('DEFAULT_DETAIL_LINK_TEXT'));
                InstallModel::insertSetting('MarketContactLink','value_int',0);
                InstallModel::insertSetting('MarketContactLinkText','value_text',Text::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':
                $fields = array("`id` int(30) NOT NULL AUTO_INCREMENT",
                                "`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL",
                                "`status` int(1) NOT NULL DEFAULT '0'",
                                "`header` int(1) NOT NULL DEFAULT '0'",
                                "`menu` int(1) NOT NULL DEFAULT '0'",
                                "`sidebar` int(1) NOT NULL DEFAULT '0'",
                                "`footer` int(1) NOT NULL DEFAULT '0'",
                                "`created` datetime NOT NULL",
                                "`modified` datetime NOT NULL");
                self::createTable("plugins",$fields,"name");
                if (!self::finishUpgrade('BETA 0.17.0')) {
                    break;
                }
            case 'BETA 0.17.0':
                self::alterTable("offers","add","slug","varchar",200,0,"null","null","id");
                self::alterTable("offers","add_index","slug",0,0,0,0,0,0);
                $offers = OfferModel::getOffers(array('howMany' => 2000, 'orderBy' => 'id ASC'));
                if ($offers['number'] > 0) {
                    foreach ($offers['offers'] as $offer) {
                        $slug = Helper::slugify($offer->title);
                        $slug_id = OfferModel::getOfferIdBySlug($slug);
                        if ($slug_id != false && $slug_id != $offer->id) {
                            $slug = $slug."-".$offer->id;
                        }
                        OfferModel::updateOffer('slug', $slug, $offer->id);
                    }
                }
                self::alterTable("profiles","add","slug","varchar",200,0,"null","null","id");
                self::alterTable("profiles","add_index","slug",0,0,0,0,0,0);
                $profiles = UserProfileModel::getProfiles(array('howMany' => 2000, 'orderBy' => 'id ASC'));
                if ($profiles['number'] > 0) {
                    foreach ($profiles['data'] as $profile) {
                        $slug = Helper::slugify($profile->company_name);
                        $slug_id = UserProfileModel::getProfileIdBySlug($slug);
                        if ($slug_id != false && $slug_id != $profile->id) {
                            $slug = $slug."-".$profile->id;
                        }
                        UserProfileModel::updateUserProfile('slug', $slug, $profile->id);
                    }
                }
                if (!self::finishUpgrade('BETA 0.18.0')) {
                    break;
                }
            case 'BETA 0.18.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;
                break;
            case 'add_index':
                $sql = "ALTER TABLE ".$prefix.$table." ADD INDEX `".$columnName."` (`".$columnName."`)";
                break;
        }
        $database->query($sql);

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

    public static function createTable($tableName, $fields, $checkColumnName)
    {
        self::$upgradesTotal++;
        $prefix = Config::get('DB_PREFIX');
        $database = DatabaseFactory::getFactory()->getConnection();

        if (self::checkTableUpgradeStatus($tableName,'add',$checkColumnName,'','','')) {
            self::$upgradesSuccessful++;
            return true;
        }

        $sql = "CREATE TABLE IF NOT EXISTS `".$prefix.$tableName."` (
                   ".implode(',',$fields).",
                   PRIMARY KEY (`id`)
                ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;";
        $database->query($sql);
        if (self::checkTableUpgradeStatus($tableName,'add',$checkColumnName,'','','')) {
            self::$upgradesSuccessful++;
        }

        if (self::$upgradesTotal == self::$upgradesSuccessful) {
            return true;
        } else {
            return false;
        }
    }

    public 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 * FROM information_schema.statistics
                        WHERE table_schema = :db_name
                          AND table_name = :table_name
                          AND column_name = :column_name
                        LIMIT 1";
                $query = $database->prepare($sql);
                $query->bindParam(':db_name',       $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() == 0) {
                    return true;
                } else {
                    return false;
                }
                break;
            case 'add_index':
                $sql = "SELECT * FROM information_schema.statistics
                        WHERE table_schema = :db_name
                          AND table_name = :table_name
                          AND column_name = :column_name
                        LIMIT 1";
                $query = $database->prepare($sql);
                $query->bindParam(':db_name',       $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;
        }
    }

    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(Text::get('PLATFORM_UPGRADE_SUCCESSFUL'),$version));
            return true;
        } else {
            Session::add('feedback_negative',
                         PA::filter(Text::get('PLATFORM_UPGRADE_UNSUCCESSFUL'),$version));
            return false;
        }
    }
}
