import { LasalRuntimeSigElement, SigPolymer } from '../../sigmatek/sig-element/sig-element.js';
import { Usermanager } from '../sig-control-user-mixin/sig-control-user-mixin.js';
import "../sig-control-input/sig-control-input.js";
import "../sig-control-button/sig-control-button.js";
import "../sig-control-listview/sig-control-listview.js";
import "../sig-control-titlebar/sig-control-titlebar.js";
import '../sig-control-input/sig-control-input-css.js';
import '../sig-control-button/sig-control-button-css.js';
import '../sig-control-listview/sig-control-listview-css.js';
import '../sig-control-titlebar/sig-control-titlebar-css.js';
import "../sig-control-scrollbar/sig-control-scrollbar-css.js";

export class LasalRuntimeSigControlUserDetail extends Usermanager(LasalRuntimeSigElement) {

    static get is() {
        return "sig-control-user-detail";
    }

    static get importMeta() { return import.meta; }

    static get template() {
        return SigPolymer.html`
            <style
                include="sig-element-css sig-control-input-css sig-control-button-css sig-control-listview-css sig-control-titlebar-css sig-control-scrollbar-css">
                :host {
                    
                    color: var(--theme-sig-control-user-detail-color, rgba(255, 255, 255, 1));
                    background-color: var(--theme-sig-control-user-detail-background-color, rgba(42, 42, 42, 1));
                    border-width: var(--theme-sig-control-user-detail-border-width, 0);
                    border-color: var(--theme-sig-control-user-detail-border-color, transparent);
                    border-style: var(--theme-sig-control-user-detail-border-style, none);
                    border-radius: var(--theme-sig-control-user-detail-border-radius, 0);

                    
                    display: block;
                    position: absolute;
                    overflow: var(--theme-sig-control-user-detail-overflow, hidden);
                }

                :host * {
                    
                    @apply --notextselect;
                    margin: 0;
                    padding: 0;
                }

                .clearfix:after {
                    
                    @apply --clearfix
                }

                .sig-control-user-detail {
                    
                    position: relative;
                    width: 100%;
                    height: 100%;
                    
                    text-decoration: inherit;
                }

                .label {
                    height: auto;
                    display: block;
                    font-size: var(--theme-sig-control-user-detail-label-font-size, 11px);
                    color: var(--theme-sig-control-user-detail-label-color, rgba(215, 215, 215, 1));
                    text-align: left;
                }

                .input {
                    width: 100%;
                    height: 30px;
                    position: unset;
                    margin-bottom: 10px !important;
                }

                .input.last {
                    margin-bottom: 0;
                }

                .buttons {
                    clear: both;
                    border-top: 1px solid var(--theme-sig-control-user-detail-button-horizontal-separator-color, rgba(86, 89, 97, 1));
                    height: auto;
                    padding: 0 10px !important;
                }

                .button {
                    position: unset;
                }

                .button.default {
                    margin: var(--theme-sig-control-user-detail-button-margin, 10px) 0;
                }

                .button.right {
                    margin-left: var(--theme-sig-control-user-detail-button-margin, 10px);
                    float: right;
                }

                .button.left {
                    margin-right: var(--theme-sig-control-user-detail-button-margin, 10px);
                    float: left;
                }

                .button.disabled {
                    opacity: var(--theme-sig-control-user-detail-button-disabled-opacity, .4);
                    pointer-events: none !important;
                }

                .roles {
                    display: none;
                    flex: 1 1 100%;
                    position: relative;
                    min-height: 45px;
                    overflow: auto;
                }

                .rolelist {
                    top: 0;
                    left: 0;
                    
                    min-width: 100%;
                    width: 100%;
                    min-height: 100%;
                    height: 100%;
                }

                .content {
                    display: flex;
                    flex-flow: column;
                    align-items: stretch;
                    height: 100%;
                    background-color: var(--theme-sig-control-user-detail-background-color, rgba(42, 42, 42, 1));
                }

                .form {
                    overflow: auto;
                    margin: 10px 10px !important;
                    flex: 1 1 100%;
                    width: calc(100% - 20px);
                    height: 100%;
                }

                .inner {
                    display: flex;
                    flex-flow: column;
                    align-items: stretch;
                    height: 100%;
                }

                .title {
                    height: auto;
                    flex: 0 1 auto;
                }

                .inputs {
                    clear: both;
                    display: none;
                    flex: 0 1 auto;
                    height: auto;
                }

                .floatleft {
                    float: left;
                    width: calc(50% - 5px);
                    margin: 0 0 10px 0 !important;
                    padding: 0 5px 0 0 !important;
                    height: auto;
                }

                .floatright {
                    float: right;
                    width: 50%;
                    height: auto;
                }

                .clear {
                    clear: both;
                    height: auto;
                }

                #passwordold,
                #passwordnew,
                #firstname,
                #lastname,
                #accessnumber {
                    margin: 0px;
                    width: 100%;
                }

                :host([mode="view"]) .inputs,
                :host([mode="update"]) .inputs,
                :host([mode="create"]) .inputs,
                :host([mode="view"]) .roles,
                :host([mode="update"]) .roles,
                :host([mode="create"]) .roles,
                :host([isdesignmode]) .inputs,
                :host([isdesignmode]) .roles {
                    display: block !important;
                }

                .idle {
                    width: 100%;
                    height: 100%;
                    color: inherit;
                    padding: 20px 0 !important;
                    text-align: center;
                    display: none;
                }

                :host([mode="idle"]) .idle {
                    display: block;
                }

                :host([isdesignmode]) .idle {
                    display: none;
                }

                :host(:not([isdesignmode])) .inactive {
                    pointer-events: none !important;
                    opacity: .8;
                    height: auto;
                }

                .hidden {
                    display: none;
                }

                :host([hidebuttons]) .buttons,
                :host([hidetitle]) sig-control-titlebar,
                :host([hiderolelist]) .roles,
                :host([hideinputs]) .inputs,
                :host([hidelabels]) .label,
                :host([hiderolelist]) label.list {
                    display: none !important;
                }

                :host sig-control-button {
                    height: var(--theme-sig-element-height, 40px);
                    width: var(--theme-sig-element-width, 90px);
                    
                    --theme-sig-control-button-padding: 2px;
                }

                :host sig-control-input {
                    
                   
                   height: var(--theme-sig-element-height, 26px);
                    --theme-sig-control-input-field-position: relative;
                    --theme-sig-control-input-placeholder-color: var(--theme-sig-control-user-detail-input-placeholder-color, rgba(142, 142, 142, 1));
                }

                :host sig-control-titlebar {
                    position: unset;
                    display: block;
                    width:100%;
                    height: var(--theme-sig-element-height, 26px);
                    
                }

                :host sig-control-listview {
                    position: unset;
                }
            </style>

            <div class="sig-control-user-detail clearfix">
                <div class="content">
                    <div class="title">
                        <sig-control-titlebar id="titlebar" value="[[texts.caption]]"
                            shadowactive="[[titlebarshadowactive]]" applybordereffect="[[applybordereffect]]">
                        </sig-control-titlebar>
                    </div>
                    <div id="form" class="form">
                        <div class="inner">
                            <div id="idle" class="idle">
                                [[texts.pleaseSelectUserFirst]]
                                <template is="dom-if" if="[[permissions.createUser]]">
                                    [[texts.orAddUser]]
                                </template>
                            </div>

                            <div id="inputs" class="inputs">
                                <sig-control-input id="id" class="input default hidden" placeholder="ID"
                                    titletext="[[texts.kbEnterUserID]]" shadowactive="[[inputfieldshadowactive]]"
                                    shadowpressedactive="[[inputfieldshadowactive]]">
                                </sig-control-input>
                                <div class="clear">
                                    <label class="label">[[texts.userName]]</label>
                                    <sig-control-input id="username" class="input default" placeholder=[[texts.userName]]
                                        titletext="[[texts.kbEnterUserName]]" shadowactive="[[inputfieldshadowactive]]"
                                        shadowpressedactive="[[inputfieldshadowactive]]">
                                    </sig-control-input>
                                </div>
                                <div class="floatleft">
                                    <label class="label">[[texts.firstName]]</label>
                                    <sig-control-input id="firstname" class="input default" placeholder=[[texts.firstName]]
                                        titletext="[[texts.kbEnterFirstName]]" shadowactive="[[inputfieldshadowactive]]"
                                        shadowpressedactive="[[inputfieldshadowactive]]">
                                    </sig-control-input>
                                </div>
                                <div class="floatright">
                                    <label class="label">[[texts.lastName]]</label>
                                    <sig-control-input id="lastname" class="input default" placeholder=[[texts.lastName]]
                                        titletext="[[texts.kbEnterLastName]]" shadowactive="[[inputfieldshadowactive]]"
                                        shadowpressedactive="[[inputfieldshadowactive]]">
                                    </sig-control-input>
                                </div>
                                <div class="clear">
                                    <label class="label">[[texts.description]]</label>
                                    <sig-control-input id="info" class="input default" placeholder=[[texts.description]]
                                        titletext="[[texts.kbEnterDescription]]" shadowactive="[[inputfieldshadowactive]]"
                                        shadowpressedactive="[[inputfieldshadowactive]]">
                                    </sig-control-input>
                                </div>
                                <div class="floatleft">
                                    <label class="label">[[texts.newPassword]]</label>
                                    <sig-control-input id="passwordold" class="input default" ispassword
                                        placeholder=[[texts.newPassword]] titletext="[[texts.kbEnterNewPassword]]"
                                        shadowactive="[[inputfieldshadowactive]]"
                                        shadowpressedactive="[[inputfieldshadowactive]]">
                                    </sig-control-input>
                                </div>
                                <div class="floatright">
                                    <label class="label">[[texts.repeatPassword]]</label>
                                    <sig-control-input id="passwordnew" class="input default last" ispassword
                                        placeholder=[[texts.repeatPassword]] titletext="[[texts.kbRepeatNewPassword]]"
                                        shadowactive="[[inputfieldshadowactive]]"
                                        shadowpressedactive="[[inputfieldshadowactive]]">
                                    </sig-control-input>
                                </div>
                                <div class="clear">
                                <label class="label">[[texts.accessNumber]]</label>
                                <sig-control-input id="accessnumber" class="input default" placeholder=[[texts.accessNumber]]
                                    titletext="[[texts.kbEnterAccessNumber]]" shadowactive="[[inputfieldshadowactive]]"
                                    shadowpressedactive="[[inputfieldshadowactive]]" type="numeric" ignoremin ignoremax>
                                </sig-control-input>
                                </div>
                                <div class="clear">
                                    <label class="label list">[[texts.roles]]</label>
                                </div>
                            </div>
                            <div class="roles">
                                <sig-control-listview id="listview" class="rolelist"></sig-control-listview>
                            </div>
                        </div>
                    </div>

                    <div id="buttons" class="buttons clearfix">
                        <template is="dom-if" if="[[!hidebuttons]]">

                            <template is="dom-if"
                                if="[[_isValidButton('save', 'createUser; updateUser;updateOwnUsername;updateOwnPW;updateOwnInfo', permissions, mode, timestamp)]]">
                                <sig-control-button id="saveuser" sigbtntext="[[texts.save]]" class="button default right"
                                    on-up="_saveUser"></sig-control-button>
                            </template>
                            <template is="dom-if" if="[[_isValidButton('cancel', 'none', permissions, mode, timestamp)]]">
                                <sig-control-button id="cancel" sigbtntext="[[texts.cancel]]" class="button default left"
                                    on-up="_cancel"></sig-control-button>
                            </template>
                            <template is="dom-if"
                                if="[[_isValidButton('edit', 'updateUser;updateOwnUsername;updateOwnPW;updateOwnInfo', permissions, mode, timestamp)]]">
                                <sig-control-button id="edituser" sigbtntext="[[texts.edit]]" class="button default right"
                                    on-up="_editUser"></sig-control-button>
                            </template>
                            <template is="dom-if"
                                if="[[_isValidButton('new', 'createUser', permissions, mode, timestamp)]]">
                                <sig-control-button id="newuser" sigbtntext="[[texts.new]]" class="button default right"
                                    on-up="_newUser"></sig-control-button>
                            </template>

                        </template>
                    </div>

                </div>
            </div>
            `
    }

    static get properties() {
        let props = {
            isloggedin: {
                type: Boolean,
                value: false,
                observer: '_toggleIsLoggedin'
            },
            activeuser: {
                type: Object,
                value: null,
                observer: '_updateUserPermissions'
            },
            hidetitle: {
                type: Boolean,
                value: false,
                reflectToAttribute: true
            },
            hideinputs: {
                type: Boolean,
                value: false,
                reflectToAttribute: true
            },
            hiderolelist: {
                type: Boolean,
                value: false,
                reflectToAttribute: true
            },
            hidebuttons: {
                type: Boolean,
                value: false,
                reflectToAttribute: true
            },
            hidelabels: {
                type: Boolean,
                value: false,
                reflectToAttribute: true
            },
            mode: {
                type: String,
                value: 'idle', 
                observer: '_updateMode',
                reflectToAttribute: true
            },
            isEditing: {
                type: Boolean,
                value: false,
                observer: '_toggleForm'
            },
            user: {
                type: Object,
                value: null,
                observer: '_updateForm'
            },
            inputfieldshadowactive: {
                type: Boolean,
                value: false,
                reflectToAttribute: true
            },
            titlebarshadowactive: {
                type: Boolean,
                value: false,
                reflectToAttribute: true
            },
            titletext: {
                type: String,
                value: '',
                observer: '_switchLang'
            },
            listviewisactive: {
                type: Boolean,
                value: false,
                observer: '_toggleListView'
            }
        }
        return props;
    }

    constructor() {
        super();
        this.umApi = window.sigApi.userManager;
        this.wmApi = window.sigApi.windowManager;
        this.tmApi = window.sigApi.textManager;
        this.utilsApi = window.sigApi.sigUtils;
        this.constApi = (window.sigApi && window.sigApi.SIG_CONST) ? window.sigApi.SIG_CONST : null;
        this.controlTextList = this.getControlTextListName();
        this.allowedButtons = [];
        this.iswindow = false;
        this.permissions = {};
        this.data = null;
        this.config = null;
        this.closeaftercreate = false;
        this.closeaftercreate = false;
        this.closeaftercancel = false;
        this.backupuser = null;
        this.source = null;
        this.timestamp = Date.now();
        this.selectedRole = null;
        this.markedRoles = null;
        this.clearRoles = false;
        this.applybordereffect = false;
        this.texts = {};

        if (!this.isdesignmode) {
            this.sigAddEventListener('LANGUAGE_CHG', (majorId, minorId, msg) => {
                this._switchLang(majorId, minorId, msg);
            }, 'runtimeEvent');

            this.sigAddEventListener('USER_CREATED', (majorId, minorId, msg) => {
                this._userCreated(majorId, minorId, msg);
            }, 'runtimeEvent');

            this.sigAddEventListener('USER_UPDATED', (majorId, minorId, msg) => {
                this._userUpdated(majorId, minorId, msg);
            }, 'runtimeEvent');

            this.sigAddEventListener('USER_DELETED', (majorId, minorId, msg) => {
                this._userDeleted(majorId, minorId, msg);
            }, 'runtimeEvent');

            this.sigAddEventListener('USER_RESTORED', (majorId, minorId, msg) => {
                this._userRestored(majorId, minorId, msg);
            }, 'runtimeEvent');

            this.sigAddEventListener('USER_LOGGED_IN', (majorId, minorId, msg) => {
                this._userLoggedIn(majorId, minorId, msg);
            }, 'runtimeEvent');

            this.sigAddEventListener('USER_LOGGED_OUT', (majorId, minorId, msg) => {
                this._userLoggedOut(majorId, minorId, msg);
            }, 'runtimeEvent');

            this.sigAddEventListener('SEND_USER_DATA', (majorId, minorId, msg) => {
                this._receivedData(majorId, minorId, msg);
            }, 'runtimeEvent');
        }
    }

    connectedCallback() {
        super.connectedCallback();
        this._init();
    }

    disconnectedCallback() {
        super.disconnectedCallback();
        this.umApi = null;
        this.wmApi = null;
        this.tmApi = null;
        this.utilsApi = null;
        this.allowedButtons = null;
        this.permissions = null;
        this.data = null;
        this.config = null;
        this.backupuser = null;
        this.source = null;
        this.selectedRole = null;
        this.markedRoles = null;
        this.texts = null;
    }

    _init() {
        this.isloggedin = this.umApi.isUserLoggedIn();
        this._switchLang();
        this._setRoleListProps();
        SigPolymer.afterNextRender(this, function (params) {
            if (this.context) this.iswindow = (this.context.type === 'window') ? true : false;

            if (this.iswindow) {
                this.$.listview.disableautodeactivate = true;

                this.sigAddEventListener('jspanelbeforeclose', (evt) => {
                    if (evt.detail === this.context.instanceId) {
                        this._clearUser();
                        this._switchMode('idle');
                    }
                }, 'jsEvent', document);
            }

            this._renderRoleList();
            this._applFontObjects();
            if (this.isdesignmode) this.listviewisactive = true;
        });
    }

    _hasNoErrors(result) {
        return (result.status || result.message || result.stack) ? false : true;
    }

    async _switchLang(majorId, minorId, msg) {
        if (this.tmApi) {
            const texts = await this.tmApi.getTextsAsync(this._getTextsObject());
            if (this.titletext !== '') texts[this.controlTextList].caption = this.titletext;
            this.texts = texts[this.controlTextList];
        }
        this._renderRoleList();
    }

    designerOnLanguageChanged() {
        this._switchLang();
    }

    async designerOnObjectStoreUpdate(data) {
        const textListChanged = await this.tmApi.isTextListUpdate(data, this.controlTextList);
        if (textListChanged) this._switchLang();
    }

    _getTextsObject() {
        return {
            [this.controlTextList]: {
                caption: 'User detail',
                id: 'ID',
                userName: 'User name',
                firstName: 'First name',
                lastName: 'Last name',
                description: 'Description',
                accessNumber: 'Accessnumber',

                password: 'Password',
                enterPassword: 'Enter password',
                newPassword: 'New Password',
                repeatPassword: 'Repeat Password',

                edit: 'Edit',
                view: 'View',
                save: 'Save',
                cancel: 'Cancel',
                new: 'New',

                info: 'Info',
                roles: 'Roles',

                none: 'none',
                notAvailable: 'not available',

                pleaseSelectUserFirst: 'Please select a user first',
                orAddUser: 'or add a new one',

                new: 'New',
                details: 'Details',

                kbEnterUserID: 'Enter id',
                kbEnterUserName: 'Enter username',
                kbEnterFirstName: 'Enter first name',
                kbEnterLastName: 'Enter last name',
                kbEnterDescription: 'Enter description',
                kbEnterAccessNumber: 'Enter accessnumber',
                kbEnterNewPassword: 'Enter new password',
                kbRepeatNewPassword: 'Repeat new password'
            }
        }
    }

    _userCreated(majorId, minorId, msg) {
        this.user = msg.user;
        this._renderRoleList();
    }

    _userUpdated(majorId, minorId, msg) {
        if (this.user !== null && this.user.id === msg.user.id && !this.isEditing) {
            this.user = msg.user;
            this._renderRoleList();
        }
    }

    _userDeleted(majorId, minorId, msg) {
        if ((this.user !== null && this.user.id === msg.id) || (this.user !== null && this.user.userName === msg.userName)) {
            this._clearUser();
            this._switchMode('idle');
        }
    }

    _userRestored(majorId, minorId, msg) {
        this._renderRoleList();
    }

    _userLoggedIn(majorId, minorId, msg) {
        const user = msg.user;
        if (this.isloggedin && user && this.activeuser.id !== user.id) this.isloggedin = false;
        this.isloggedin = true;
    }

    _userLoggedOut(majorId, minorId, msg) {
        this.isloggedin = false;
    }

    _setRoleListProps() {
        this.$.listview.disablekeys = false;
        this.$.listview.disablemultiselect = false;
        this.$.listview.hideheader = true;
        this.$.listview.activemarked = true;
    }

    async _renderRoleList() {
        if (this.disconnected) return;
        let roles = [];
        if (!this.isdesignmode) {
            if (this.isEditing && this.permissions.grantRole) {
                if (this.user.id === 3) {
                    this.listviewisactive = false;
                    return;
                }

                this.listviewisactive = true;
                const uid = this.utilsApi.getUID();
                const result = await this.umApi.getRoleList(uid).catch(error => {
                    return error;
                });

                if (this._hasNoErrors(result)) {
                    roles = result.roles.filter(role => (this.isEditing) ? this._checkReadAccess(role.accessNumber) && role.id > 3 : true);
                    if (this.user !== null && this.user.id) {
                        roles.map(role => {
                            role.marked = false;
                            if (this.user.roles) this.user.roles.map(userRole => {
                                if ((userRole === role.name || userRole.name === role.name) && this.mode === 'update') role.marked = true;
                                return role;
                            })
                        });
                    } else {
                        roles.map(role => { role.marked = false; });
                    }
                } else {
                    console.error(result);
                }
            } else {
                if (this.user !== null) {
                    if (this.user.roles) roles = this.user.roles.map((userRole) => {
                        const userRoleObj = {};
                        if (userRole.name) userRoleObj.name = userRole.name;
                        else userRoleObj.name = userRole;
                        userRoleObj.marked = false; return userRoleObj;
                    });
                }
            }
        } else {
            roles =
                [
                    {
                        id: 0,
                        name: 'role0 - selected',
                        active: true
                    },
                    {
                        id: 1,
                        name: 'role1 - selected marked',
                        marked: true,
                        active: true
                    },
                    {
                        id: 2,
                        name: 'role2 - alternate (odd)'
                    },
                    {
                        id: 3,
                        name: 'role3 - normal (even)'
                    },
                    {
                        id: 4,
                        name: 'role4 - marked',
                        marked: true
                    }];
        }


        this.data = {
            "cols": [{
                "id": "id",
                "name": "id",
                "type": "text",
                "default": "&nbsp;",
                "visible": false,
                "sortable": false
            },
            {
                "id": "marked",
                "name": "marked",
                "type": "symbol",
                "default": "&nbsp;",
                "visible": this.listviewisactive,
                "sortable": false,
                "formatDataCallback": this._formatMarked,
                "css": {
                    "width": "20px",
                    "min-width": "20px"
                }
            },
            {
                "id": "name",
                "name": "Role",
                "type": "text",
                "default": "&nbsp;",
                "visible": true,
                "sortable": false
            }],
            "data": {
                "nodes": roles
            }
        }
        this.config = {
            updateSelectionCallback: (data, pane) => {
                this._updateSelection(data, pane);
            },
            updateActiveRowCallback: (data, pane) => {
                this._updateActiveRow(data, pane);
            },
            clickCallback: (data, pane) => {
                this._updateMarkedRow(data, pane);
            },
            data: this.data,
            name: "userdetail"
        };
        if (roles[0] || (this.user && this.user.id)) {
            this.$.listview.config = this.config;
        }
    }

    _updateSelection(roles, pane) {
        this.markedRoles = roles;
        if (!this.markedRoles) this.clearRoles = true;
        else this.clearRoles = false;
    }

    _updateActiveRow(role, pane) {
        this.selectedRole = role;
        if (role.marked) {
            role.marked = false;
        }
    }

    _updateMarkedRow(row, pane) {
        this.$.listview._markRowById();
    }

    _clearInputs() {
        this.$.username.value = '';
        this.$.password.value = '';
        this.$.listview._clearActiveRow(true);
    }

    _closeWindow() {
        if (this.context.type === 'window') {
            const window = document.getElementById(this.context.instanceId);
            if (window instanceof HTMLElement) window.close();
        }
    }

    _updateMode(newval, oldval) {
        switch (newval) {
            case 'idle':
                this.isEditing = false;
                this.allowedButtons = ['new'];
                break;
            case 'view':
                this.isEditing = false;
                if (this.user.readOnly !== true) this.allowedButtons = ['edit', 'showDetails'];
                else this.allowedButtons = ['showDetails'];
                break;
            case 'update':
                this.isEditing = true;
                if (this.user.readOnly !== true) this.allowedButtons = ['save', 'cancel'];
                else this.allowedButtons = ['cancel'];
                break;
            case 'create':
                this.isEditing = true;
                this.allowedButtons = ['save', 'cancel'];
                break;
            default:
                this.isEditing = false;
                this.allowedButtons = [''];
                break;
        }
    }

    _isValidButton(button, permission, permissions, mode) {
        if ((!this.isloggedin && !this.isdesignmode) || this.disconnected) return false;
        let _isPermitted = false;
        const _permArr = permission.split(';');
        if (this.allowedButtons.indexOf(button) >= 0) {
            const allowedPerms = _permArr.filter((_permission) => (permissions[_permission.trim()] || _permission === 'none'));
            if (allowedPerms.length > 0 || this.isdesignmode) _isPermitted = true;
        }
        if (_isPermitted) setTimeout(() => this._setButtonState(), 0);
        return _isPermitted;
    }

    _receivedData(majorId, minorId, msg) {
        this.clearRoles = false;
        this.markedRoles = null;
        if (this._isValidEvent(msg.type, msg.target, msg.source)) {
            if (!this.isEditing && msg.type === 'user') {
                switch (msg.data.mode) {
                    case 'view':
                        this._viewUser(msg.data.user);
                        break;
                    case 'update':
                        const hasAccess = (msg.data.user && msg.data.user.accessNumber !== undefined) ? this._checkAccess(msg.data.user.accessNumber) : false;
                        if (hasAccess) this._editUser(msg.data.user);
                        else this._viewUser(msg.data.user);
                        break;
                    case 'create':
                        this._newUser();
                        break;
                }
            }
            this._renderRoleList();
        }
    }

    _updateForm(newval, oldval) {
        if (newval instanceof Object) {
            if (newval.id || newval.id === 0) this.$.id.value = newval.id
            if (newval.userName) this.$.username.value = newval.userName;
            else this.$.username.value = "";
            if (newval.lastName) this.$.lastname.value = newval.lastName;
            else this.$.lastname.value = "";
            if (newval.firstName) this.$.firstname.value = newval.firstName;
            else this.$.firstname.value = "";
            if (newval.info) this.$.info.value = newval.info;
            else this.$.info.value = "";
            if (newval.accessNumber) this.$.accessnumber.value = newval.accessNumber;
            else this.$.accessnumber.value = "";
            this._renderRoleList();
        } else {
            this._clearForm();
        }
    }

    async _toggleIsLoggedin(newval, oldval) {
        if (this.disconnected) return;
        if (newval) {
            if (this.activeuser === null) {
                const uid = this.utilsApi.getUID();
                const result = await this.umApi.getActiveUser(uid).catch(error => {
                    return error;
                });
                if (this._hasNoErrors(result)) {
                    this.activeuser = result.user;
                } else {
                    console.error(result);
                }
            }
        } else {
            this.activeuser = null;
            this._clearUser();
            this._switchMode('idle');
        }
    }

    _toggleForm(newval, oldval) {
        if (newval) {
            this.$.inputs.classList.remove('inactive');
            if (this.permissions.grantRole) {
                this.listviewisactive = true;
            } else {
                this.listviewisactive = false;
            }
        } else {
            this.$.inputs.classList.add('inactive');
            this.listviewisactive = false;
        }
    }

    _viewUser(user = null) {
        this.user = user;
        this._backupUser();
        this.mode = 'neutral';
        this._switchMode('view');
    }

    _editUser(user = null) {
        if (!(user instanceof Event)) this.user = user;
        this._backupUser();
        this._switchMode('update');
    }

    _newUser() {
        this._clearUser(true, false);
        this._prefillFields();
        this._switchMode('create');
    }

    _prefillFields() {
        this.user = {
            accessNumber: this.constApi.USER_ACCESS_NUMBER
        };
    }

    _saveUser() {
        const _formFilled = this._saveForm();
        if (_formFilled === true) {
            switch (this.mode) {
                case 'create':
                    this._createUser();
                    break;
                case 'update':
                    this._updateUser();
                    break;
            }
        }
    }

    _cancel() {
        this._clearPasswords();
        if (this.backupuser !== null) {
            this._restoreUser();
            if (this.mode === 'update') {
                this.mode = 'neutral';
                this._switchMode('view');
            } else {
                this._switchMode('idle');
            }
        } else {
            this._switchMode('idle');
        }
        if (this.closeaftercancel) {
            this._closeWindow();
        }
    }

    _switchMode(mode) {
        this.mode = mode;
        this._renderRoleList();
        if (this.mode === mode) {
            this.timestamp = Date.now();
        }
    }

    async _updateUser() {
        if (this.disconnected) return;
        const uid = this.utilsApi.getUID();
        if (this.user.passwordOld || this.user.passwordNew) {
            if (this.user.passwordOld !== this.user.passwordNew) {
                await this._showAlert(this._getTextObj('userPasswordNotMatch'), this._getTextObj('caption')).catch(error => {
                    this._log(error);
                    return error;
                });
                return;
            }
            if (!this.umApi.isValidPassword(this.user.passwordOld)) {
                await this._showAlert(this._getTextObj('userPasswordInvalid'), this._getTextObj('caption')).catch(error => {
                    this._log(error);
                    return error;
                });
                return;
            }
        }

        if (!this.umApi.isValidUsername(this.user.userName)) {
            await this._showAlert(this._getTextObj('userNameInvalid'), this._getTextObj('caption')).catch(error => {
                this._log(error);
                return error;
            });
            return;
        }

        if (!this._validateAccessNumberFormat(this.user.accessNumber)) {
            await this._showAlert(this._getTextObj('accessNumberInvalid'), this._getTextObj('caption')).catch(error => {
                this._log(error);
                return error;
            });
            return;
        }
        const result = await this.umApi.updateUser(this.user, this.id, undefined, undefined, uid).catch(error => {
            return error;
        })
        if (this._hasNoErrors(result)) {
            this._backupUser();
        } else {
            await this._showAlert(result.errortxt, this._getTextObj('alertTitle', [result.status])).catch(error => {
                this._log(error);
                return error;
            });
            this._restoreUser();
        }
        this._clearPasswords();
        this._switchMode('view');
        if (this.closeafterupdate) {
            this._closeWindow();
        }
    }

    async _createUser() {
        if (this.disconnected) return;
        if (!this.user.userName || this.user.userName.trim() === '') {
            await this._showAlert(this._getTextObj('userCouldnotBeCreated'), this._getTextObj('caption')).catch(error => {
                this._log(error);
                return error;
            });
            return;
        } else if (!this.umApi.isValidUsername(this.user.userName)) {
            await this._showAlert(this._getTextObj('userCouldnotBeCreated'), this._getTextObj('caption')).catch(error => {
                this._log(error);
                return error;
            });
            return;
        }

        if (this.user.passwordOld && this.user.passwordNew) {
            if (this.user.passwordOld !== this.user.passwordNew) {
                await this._showAlert(this._getTextObj('userPasswordNotMatch'), this._getTextObj('caption')).catch(error => {
                    this._log(error);
                    return error;
                });
                return;
            } else if (!this.umApi.isValidPassword(this.user.passwordOld)) {
                await this._showAlert(this._getTextObj('userPasswordNotMatch'), this._getTextObj('caption')).catch(error => {
                    this._log(error);
                    return error;
                });
                return;
            }
        } else if (!this.user.passwordOld || !this.user.passwordNew) {
            await this._showAlert(this._getTextObj('userCouldnotBeCreated'), this._getTextObj('caption')).catch(error => {
                this._log(error);
                return error;
            });
            return;
        }

        if (!this._validateAccessNumberFormat(this.user.accessNumber)) {
            await this._showAlert(this._getTextObj('accessNumberInvalid'), this._getTextObj('caption')).catch(error => {
                this._log(error);
                return error;
            });
            return;
        }
        const uid = this.utilsApi.getUID();
        const result = await this.umApi.createUser(this.user, this.id, undefined, undefined, uid).catch(error => {
            return error;
        })
        if (this._hasNoErrors(result)) {
            if (result.data[0]) this.user = result.data[0];
            this._backupUser();
        } else {
            await this._showAlert(result.errortxt, this._getTextObj('caption')).catch(error => {
                this._log(error);
                return error;
            });
            this._restoreUser();
        }
        this._switchMode('view');
        if (this.closeaftercreate) {
            this._closeWindow();
        }
    }

    _saveForm() {
        if (this.user === null) this.user = {};
        if (this.$.username.value) this.user.userName = this.$.username.value;
        else {
            this._showAlert(this._getTextObj('userCouldnotBeCreated'), this._getTextObj('caption')).catch(error => {
                this._log(error);
                return false;
            });
            return false;
        }

        if (this.$.lastname.value) this.user.lastName = this.$.lastname.value;
        else this.user.lastName = '';
        if (this.$.firstname.value) this.user.firstName = this.$.firstname.value;
        else this.user.firstName = '';

        this.user.info = this.$.info.value;

        if (this.$.passwordold.value && this.$.passwordold.value.length > 0) {
            this.user.passwordOld = this.$.passwordold.value;
        } else {
            delete this.user.passwordOld;
        }
        if (this.$.passwordnew.value && this.$.passwordnew.value.length > 0) {
            this.user.passwordNew = this.$.passwordnew.value;
        } else {
            delete this.user.passwordNew;
        }
        if (this.$.accessnumber.value) this.user.accessNumber = this.$.accessnumber.value;
        else this.user.accessNumber = 0xFFFF;
        if (this.permissions.grantRole && this.clearRoles === true) {
            this.user.roles = null;
        }
        else if (this.permissions.grantRole && this.markedRoles && this.clearRoles !== true) {
            this.user.roles = this.markedRoles;
        }
        return true;
    }

    _clearForm() {
        this.user = {};
        this.$.username.id = undefined;
        this.$.username.value = undefined;
        this.$.lastname.value = undefined;
        this.$.firstname.value = undefined;
        this.$.info.value = undefined;
        this.$.passwordold.value = undefined;
        this.$.passwordnew.value = undefined;
        this.$.accessnumber.value = undefined;
        this._renderRoleList();
    }

    _clearPasswords(clearOld = true, clearNew = true) {
        if (clearOld) this.$.passwordold.value = undefined;
        if (clearNew) this.$.passwordnew.value = undefined;
    }

    _backupUser() {
        if (this.user && this.user.id) this.backupuser = Object.assign({}, this.user);
    }

    _restoreUser() {
        if (this.backupuser && this.backupuser.id) {
            const uid = this.utilsApi.getUID();
            this.umApi.getUserDetail(this.backupuser.id, uid).then((obj) => {
                this.user = obj.user;
            });
        }
    }

    _clearUser(clearUser = true, clearBackupUser = true) {
        if (clearUser) this.user = null;
        if (clearBackupUser) this.backupuser = null;
    }

    async _updateUserPermissions(newval, oldval) {
        if (this.disconnected) return;
        let uid = this.utilsApi.getUID();
        const resultDefaultPermissions = await this.umApi.getDefaultPermissions(uid).catch(error => error);
        if (this._hasNoErrors(resultDefaultPermissions)) this.permissions = resultDefaultPermissions.permissions;

        if (this.isloggedin && newval && newval !== null) {
            uid = this.utilsApi.getUID();
            const result = await this.umApi.getUserPermissions(this.activeuser, uid).catch(
                error => {
                    return error;
                });
            if (this._hasNoErrors(result)) {
                this.permissions = result.permissions;
            } else {
                console.error(result);
                this.permissions = resultDefaultPermissions.permissions;
            }
        } else {
            this.permissions = resultDefaultPermissions.permissions;
        }
        this._renderRoleList();
        this._setButtonState(this.user);
    }

    _isValidEvent(type, target, source) {
        let isValidSource = false,
            isValidTarget = false,
            isValidType = false;
        if (type && type === 'user') isValidType = true;
        if (this.source) {
            if (this.source === source) isValidSource = true;
        } else { 
            isValidSource = true;
        }
        if ((Array.isArray(target) && (target.indexOf(this.id) > -1) || target === null)) {
            isValidTarget = true;
        }
        return (isValidType && isValidTarget && isValidSource) ? true : false;
    }

    _formatMarked(marked, row) {
        return '&nbsp;';
    }

    _toggleListView(newval, oldval) {
        if (newval) {
            this.$.listview.readonly = false;
            this.$.listview.isactive = true;
            this.$.listview.classList.remove('inactive');
        } else {
            this.$.listview.readonly = true;
            this.$.listview.isactive = false;
            this.$.listview.classList.add('inactive');
        }
    }

    _setButtonState(user = this.user) {
        const buttons = this.shadowRoot.querySelectorAll('#buttons sig-control-button');
        const hasAccess = (user && user.accessNumber !== undefined) ? this._checkAccess(user.accessNumber) : false;
        buttons.forEach(button => {
            let enableButton = false;
            switch (button.id) {
                case 'newuser':
                case 'cancel':
                    enableButton = true;
                    break;
                case 'saveuser':
                    if (this.mode === 'create' || hasAccess) enableButton = true;
                    break;
                case 'edituser':
                    if (hasAccess && this.permissions.updateUser ||
                        (hasAccess && this.activeuser.id === user.id && this._updateSelfPermissions()))
                        enableButton = true;
                    break;
                case 'linktoken':
                default:
                    if (hasAccess) enableButton = true;
                    break;
            }
            if (enableButton) this._enableButton(button);
            else this._disableButton(button);
        });
    }
}
customElements.define(LasalRuntimeSigControlUserDetail.is, LasalRuntimeSigControlUserDetail);