import Immutable from 'immutable';
import _ from 'lodash';

import DepartmentStore from 'stores/Departments';
import ConfigStore from 'stores/Config';
import AuthStore from 'stores/Auth';
import SessionStore from 'stores/Sessions';
import Url from 'lib/Url';
import { formatDate } from 'lib/i18n';

const DEFAULTS = {
    id: undefined,
    birthday: undefined,
    timezone: undefined,
    department: undefined,
    email: undefined,
    contacts: undefined,
    aliases: undefined,
    gender: undefined,
    groups: undefined,
    password_change_required: undefined,
    name: undefined,
    login: undefined,
    nickname: undefined,
    position: undefined,
    is_enabled: true,
    is_dismissed: undefined,
    role: undefined,
    internal: undefined,
    cache_key: undefined,
    language: undefined,
    avatar_id: undefined,
};

class User extends Immutable.Record(DEFAULTS) {
    static PRIMARY_KEY = 'id';
    static TYPE_NAME = 'user';

    static create(data, cacheKey) {
        const nextData = _.pick(data, Object.keys(DEFAULTS));

        nextData.cache_key = cacheKey;

        if (nextData.id !== undefined && nextData.id !== null) {
            nextData.id = String(nextData.id);
        }

        return new User(Immutable.fromJS(nextData));
    }

    static getDefaultAvatar() {
        return Url.build(ConfigStore.get('ui.avatar.url'), {
            id: '0', login: '0', size: 200,
        });
    }

    getType() {
        return User.TYPE_NAME;
    }

    getId() {
        return this.get(User.PRIMARY_KEY);
    }

    getNickname() {
        return this.get('nickname') || this.get('login');
    }

    equals(x) {
        return (x instanceof User) && x.getId() === this.getId();
    }

    getUrl() {
        if (ConfigStore.get('ui.staffModeEnabled') && AuthStore.getViewMode() !== 'admin') {
            return this.getExternalStaffUrl();
        }

        return Url.getContextPath(`${this.getType()}s`, this.getId());
    }

    getExternalStaffUrl() {
        return Url.build(ConfigStore.get('ui.staff'), {
            org_id: AuthStore.getOrganizationId(),
            uid: this.getId(),
            nickname: this.getNickname(),
        });
    }

    getAvatar() {
        let avatarId = this.get('avatar_id');

        if (!avatarId) {
            let session = SessionStore.get(this.getId());

            avatarId = session && session.get('avatar_id');
        }

        let url = Url.build(ConfigStore.get('ui.avatar.url'), {
            id: avatarId || '0/0-0',
            login: this.getNickname() || '0',
            size: 200,
        });

        const cacheKey = this.get('cache_key');

        if (cacheKey) {
            // при смене аватара обновляем его url через обновление cache_key
            url += `${url.indexOf('?') === -1 ? '?' : '&'}k=${this.get('cache_key')}`;
        }

        return url;
    }

    _getLocalized(path, locale) {
        locale = locale || AuthStore.getLocale();

        let value = this.getIn(path);

        if (value && typeof value !== 'string' && value.get) {
            value = value.get(locale);
        }

        return value;
    }

    _getCompoundName(components, locale) {
        locale = locale || AuthStore.getLocale();

        let name = components
            .map(component => this._getLocalized(['name', component], locale))
            .filter(Boolean).join(' ');

        if (!name) {
            name = components
                .map(component => this._getLocalized(['name', component], 'ru'))
                .filter(Boolean).join(' ');
        }

        return name || this.getNickname();
    }

    // Иван Васильевич Петров
    getName(locale) {
        return this._getCompoundName(['first', 'middle', 'last'], locale);
    }

    // Петров Иван Васильевич
    // NB: для сортировок - регистронезависимый toSortableString()
    getAlphabeticalName(locale) {
        return this._getCompoundName(['last', 'first', 'middle'], locale);
    }

    toSortableString(locale) {
        return (this.getAlphabeticalName(locale) || '').toLowerCase();
    }

    // Иван Васильевич
    getShortName(locale) {
        return this._getCompoundName(['first', 'middle'], locale);
    }

    // Иван Петров
    getShortFullName(locale) {
        return this._getCompoundName(['first', 'last'], locale);
    }

    getFirstName(locale) {
        return this._getLocalized(['name', 'first'], locale || AuthStore.getLocale()) ||
            this._getLocalized(['name', 'first'], 'ru');
    }

    getMiddleName(locale) {
        return this._getLocalized(['name', 'middle'], locale || AuthStore.getLocale()) ||
            this._getLocalized(['name', 'middle'], 'ru');
    }

    getLastName(locale) {
        return this._getLocalized(['name', 'last'], locale || AuthStore.getLocale()) ||
            this._getLocalized(['name', 'last'], 'ru');
    }

    getPosition(locale) {
        return this._getLocalized(['position'], locale || AuthStore.getLocale()) ||
            this._getLocalized(['position'], 'ru');
    }

    getDescription() {
        return this.getPosition();
    }

    getDepartment() {
        return DepartmentStore.get(this.get('department'));
    }

    getGroups() {
        const groups = this.get('groups');

        return groups ? groups.toArray() : [];
    }

    getContacts() {
        const contacts = this.get('contacts');

        return contacts ? contacts.toJS() : [];
    }

    getOrderedContacts() {
        // упорядочивание контактов: почта, отмеченное как главное, остальное
        return _.sortBy(this.getContacts(),
            contact => -(Number(contact.main) + Number(contact.type === 'email') * 2)
        );
    }

    getPhoneNumber() {
        const contact = _.find(this.getOrderedContacts(), { type: 'phone' });

        if (contact) {
            return contact.value;
        }
    }

    getEmail() {
        return this.get('email');
    }

    /**
     * Возвращает минимальный набор контактов:
     * основной e-mail и первые два номера телефона
     * @method  getMinimalContacts
     * @returns {Array}
     */
    getMinimalContacts() {
        const contacts = this.getContacts();

        const emails = contacts
            .filter(contact => contact.type === 'email' && contact.main)
            .slice(0, 1);

        const phoneNumbers = [];

        contacts.forEach((contact, index) => {
            if (contact.type === 'phone' && phoneNumbers.length < 2) {
                phoneNumbers.push(contact);

                // если за номером телефона следует добавочный номер,
                // добавляем добавочный в список номеров
                if (contacts[index + 1] && contacts[index + 1].type === 'phone_extension') {
                    phoneNumbers.push(contacts[index + 1]);
                }
            }
        });

        return emails.concat(phoneNumbers);
    }

    getGender() {
        return this.get('gender');
    }

    getSerializedBirthDate() {
        return this.get('birthday');
    }

    getDisplayableBirthDate() {
        const birthdate = this.get('birthday');

        if (birthdate) {
            return formatDate(birthdate);
        }
    }

    getPrivateYambChatUrl() {
        return Url.build(ConfigStore.get('ui.privateYambChat'), {
            nickname: this.getNickname(),
            email: this.getEmail(),
        });
    }

    getRole() {
        return this.get('role');
    }

    isAdmin() {
        return this.getRole() === 'admin';
    }

    isDeputyAdmin() {
        return this.getRole() === 'deputy_admin';
    }
}

export default User;
