<?php
namespace common\models;

use common\behaviors\DataBehavior;
use common\behaviors\EmailActivationExpirationBehavior;
use common\components\UserFriendlyRandomKey;
use yii\base\InvalidConfigException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;

/**
 * Поля модели:
 * @property string  $key
 * @property integer $account_id
 * @property integer $type
 * @property string  $_data
 * @property integer $created_at
 *
 * Отношения:
 * @property Account $account
 *
 * Поведения:
 * @mixin TimestampBehavior
 * @mixin EmailActivationExpirationBehavior
 * @mixin DataBehavior
 */
class EmailActivation extends ActiveRecord {

    const TYPE_REGISTRATION_EMAIL_CONFIRMATION = 0;
    const TYPE_FORGOT_PASSWORD_KEY = 1;
    const TYPE_CURRENT_EMAIL_CONFIRMATION = 2;
    const TYPE_NEW_EMAIL_CONFIRMATION = 3;

    public static function tableName() {
        return '{{%email_activations}}';
    }

    public function behaviors() {
        return [
            [
                'class' => TimestampBehavior::class,
                'updatedAtAttribute' => false,
            ],
            'expirationBehavior' => [
                'class' => EmailActivationExpirationBehavior::class,
                'repeatTimeout' => 5 * 60, // 5m
                'expirationTimeout' => -1,
            ],
            'dataBehavior' => [
                'class' => DataBehavior::class,
                'attribute' => '_data',
            ],
        ];
    }

    public function getAccount() {
        return $this->hasOne(Account::class, ['id' => 'account_id']);
    }

    /**
     * @inheritdoc
     */
    public static function instantiate($row) {
        $type = ArrayHelper::getValue($row, 'type');
        if ($type === null) {
            return parent::instantiate($row);
        }

        $classMap = self::getClassMap();
        if (!isset($classMap[$type])) {
            throw new InvalidConfigException('Unexpected type');
        }

        return new $classMap[$type];
    }

    public static function getClassMap() {
        return [
            self::TYPE_REGISTRATION_EMAIL_CONFIRMATION => confirmations\RegistrationConfirmation::class,
            self::TYPE_FORGOT_PASSWORD_KEY             => confirmations\ForgotPassword::class,
            self::TYPE_CURRENT_EMAIL_CONFIRMATION      => confirmations\CurrentEmailConfirmation::class,
            self::TYPE_NEW_EMAIL_CONFIRMATION          => confirmations\NewEmailConfirmation::class,
        ];
    }

    public function beforeSave($insert) {
        if (!parent::beforeSave($insert)) {
            return false;
        }

        if ($this->key === null) {
            do {
                $this->key = $this->generateKey();
            } while ($this->isKeyExists($this->key));
        }

        return true;
    }

    protected function generateKey() : string {
        return UserFriendlyRandomKey::make();
    }

    protected function isKeyExists(string $key) : bool {
        return self::find()->andWhere(['key' => $key])->exists();
    }

}