<?php

namespace craft\migrations;

use craft\db\Migration;
use craft\db\Query;
use craft\helpers\Json;
use craft\helpers\Localization;
use craft\helpers\MigrationHelper;
use yii\base\InvalidArgumentException;

/**
 * m150428_231346_userpreferences migration.
 */
class m150428_231346_userpreferences extends Migration
{
    // Properties
    // =========================================================================

    private $_usersTable;
    private $_prefsTable;

    // Public Methods
    // =========================================================================

    /**
     * @inheritdoc
     */
    public function safeUp()
    {
        $this->_usersTable = $this->db->getSchema()->getRawTableName('{{%users}}');
        $this->_prefsTable = $this->db->getSchema()->getRawTableName('{{%userpreferences}}');

        // In case this was run in a previous update attempt
        $this->dropTableIfExists($this->_prefsTable);

        $this->_createUserPrefsTable();
        $this->_createUserPrefsIndexAndForeignKey();
        $this->_populateUserPrefsTable();

        MigrationHelper::dropForeignKeyIfExists($this->_usersTable, ['preferredLocale'], $this);
        $this->dropColumn($this->_usersTable, 'preferredLocale');
        $this->dropColumn($this->_usersTable, 'weekStartDay');
    }

    /**
     * @inheritdoc
     */
    public function safeDown()
    {
        echo "m150428_231346_userpreferences cannot be reverted.\n";

        return false;
    }

    // Private Methods
    // =========================================================================

    /**
     * Creates the userpreferences table
     */
    private function _createUserPrefsTable()
    {
        $this->createTable($this->_prefsTable, [
            'userId' => $this->integer()->notNull(),
            'preferences' => $this->text(),
            'PRIMARY KEY([[userId]])',
        ]);
    }

    /**
     * Creates an index and foreign key on the `userId` column on the userpreferences table.
     */
    private function _createUserPrefsIndexAndForeignKey()
    {
        $this->createIndex(
            $this->db->getIndexName($this->_prefsTable, 'userId', true),
            $this->_prefsTable,
            'userId',
            true
        );

        $this->addForeignKey(
            $this->db->getForeignKeyName($this->_prefsTable, ['userId']),
            $this->_prefsTable,
            'userId',
            $this->_usersTable,
            'id',
            'CASCADE'
        );
    }

    /**
     * Populates the userpreferences table.
     */
    private function _populateUserPrefsTable()
    {
        $users = (new Query())
            ->select(['id', 'preferredLocale', 'weekStartDay'])
            ->from([$this->_usersTable])
            ->where([
                'not',
                [
                    'preferredLocale' => null,
                    'weekStartDay' => '0'
                ]
            ])
            ->all($this->db);

        if (!empty($users)) {
            $rows = [];

            foreach ($users as $user) {
                $prefs = [];

                if (!empty($user['preferredLocale'])) {
                    try {
                        $prefs['language'] = Localization::normalizeLanguage($user['preferredLocale']);
                    } catch (InvalidArgumentException $e) {
                        // Do nothing.
                    }
                }

                if ($user['weekStartDay'] != 0) {
                    $prefs['weekStartDay'] = $user['weekStartDay'];
                }

                $rows[] = [$user['id'], Json::encode($prefs)];
            }

            $this->batchInsert($this->_prefsTable, [
                'userId',
                'preferences'
            ], $rows, false);
        }
    }
}
