// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, ViewChild, AfterViewChecked } from '@angular/core';
import { NgForm } from '@angular/forms';
import { PasswordSettingService } from './password-setting.service';
import { SessionService } from '../../shared/services/session.service';
import { isEmptyForm } from '../../shared/units/shared.utils';
import { MessageHandlerService } from '../../shared/services/message-handler.service';
import { InlineAlertComponent } from "../../shared/components/inline-alert/inline-alert.component";

@Component({
    selector: 'password-setting',
    templateUrl: "password-setting.component.html",
    styleUrls: ['./password-setting.component.scss', '../../common.scss']
})
export class PasswordSettingComponent implements AfterViewChecked {
    showOldPwd: boolean = false;
    showNewPwd: boolean = false;
    showReNewPwd: boolean =false;
    opened: boolean = false;
    oldPwd: string = "";
    newPwd: string = "";
    reNewPwd: string = "";
    error: any = null;

    formValueChanged: boolean = false;
    onCalling: boolean = false;
    private validationStateMap: any = {
        "newPassword": true,
        "reNewPassword": true
    };

    pwdFormRef: NgForm;
    @ViewChild("changepwdForm", {static: true}) pwdForm: NgForm;
    @ViewChild(InlineAlertComponent, {static: true})
    inlineAlert: InlineAlertComponent;

    constructor(
        private passwordService: PasswordSettingService,
        private session: SessionService,
        private msgHandler: MessageHandlerService) { }

    // If form is valid
    public get isValid(): boolean {
        if (this.pwdForm && this.pwdForm.form.get("newPassword")) {
            return this.pwdForm.valid &&
                (this.pwdForm.form.get("newPassword").value === this.pwdForm.form.get("reNewPassword").value) &&
                this.error === null;
        }
        return false;
    }

    public get valueChanged(): boolean {
        return this.formValueChanged;
    }

    public get showProgress(): boolean {
        return this.onCalling;
    }

    getValidationState(key: string): boolean {
        return this.validationStateMap[key];
    }

    handleValidation(key: string, flag: boolean): void {
        if (flag) {
            // Checking
            let cont = this.pwdForm.controls[key];
            if (cont) {
                this.validationStateMap[key] = cont.valid;
                if (cont.valid) {
                    if (key === "reNewPassword" || key === "newPassword") {
                        let cpKey = key === "reNewPassword" ? "newPassword" : "reNewPassword";
                        let compareCont = this.pwdForm.controls[cpKey];
                        if (compareCont && compareCont.valid) {
                            this.validationStateMap["reNewPassword"] = cont.value === compareCont.value;
                        }
                    }
                }
            }
        } else {
            // Reset
            this.validationStateMap[key] = true;
        }
    }

    ngAfterViewChecked() {
        if (this.pwdFormRef !== this.pwdForm) {
            this.pwdFormRef = this.pwdForm;
            if (this.pwdFormRef) {
                this.pwdFormRef.valueChanges.subscribe(data => {
                    this.formValueChanged = true;
                    this.error = null;
                    this.inlineAlert.close();
                });
            }
        }
    }

    // Open modal dialog
    open(): void {
        // Reset state
        this.formValueChanged = false;
        this.onCalling = false;
        this.error = null;
        this.validationStateMap = {
            "newPassword": true,
            "reNewPassword": true
        };
        this.pwdForm.reset();
        this.inlineAlert.close();

        this.opened = true;
    }

    // Close the modal dialog
    close(): void {
        if (this.formValueChanged) {
            if (isEmptyForm(this.pwdForm)) {
                this.opened = false;
            } else {
                // Need user confirmation
                this.inlineAlert.showInlineConfirmation({
                    message: "ALERT.FORM_CHANGE_CONFIRMATION"
                });
            }
        } else {
            this.opened = false;
        }
    }

    confirmCancel($event: any): void {
        this.opened = false;
    }

    // handle the ok action
    doOk(): void {
        if (this.onCalling) {
            return; // To avoid duplicate click events
        }

        if (!this.isValid) {
            return; // Double confirm
        }

        // Double confirm session is valid
        let cUser = this.session.getCurrentUser();
        if (!cUser) {
            return;
        }

        // Call service
        this.onCalling = true;

        this.passwordService.changePassword(cUser.user_id,
            {
                new_password: this.pwdForm.value.newPassword,
                old_password: this.pwdForm.value.oldPassword
            })
            .subscribe(() => {
                this.onCalling = false;
                this.opened = false;
                this.msgHandler.showSuccess("CHANGE_PWD.SAVE_SUCCESS");
            }, error => {
                this.onCalling = false;
                this.error = error;
                if (this.msgHandler.isAppLevel(error)) {
                    this.opened = false;
                    this.msgHandler.handleError(error);
                } else {
                    // Special case for 400
                    let msg = '' + error.error;
                    if (msg && msg.includes('old_password_is_not_correct')) {
                        this.inlineAlert.showInlineError("INCONRRECT_OLD_PWD");
                    } else {
                        this.inlineAlert.showInlineError(error);
                    }
                }
            });
    }
}
