import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service';
import {UntypedFormBuilder, UntypedFormGroup, Validators} from '@angular/forms';
import {CheckEntity, Entity} from '../../utils/entities/adminTool/entity';
import {Portal} from '../../utils/entities/adminTool/portal';
import {EnvProperties} from '../../utils/properties/env-properties';
import {Session} from '../../login/utils/helper.class';
import {UserManagementService} from '../../services/user-management.service';
import {Subscriber} from "rxjs";
import {properties} from "../../../../environments/environment";
import {AlertModal} from "../../utils/modal/alert";
import {StringUtils} from "../../utils/string-utils.class";
import {Title} from "@angular/platform-browser";
import {StakeholderService} from '../../monitor/services/stakeholder.service';
import {CommunityService} from "../../connect/community/community.service";
import {CommunityInfo} from "../../connect/community/communityInfo";
import {Stakeholder} from "../../monitor/entities/stakeholder";
import {ClearCacheService} from "../../services/clear-cache.service";
import {NotificationHandler} from "../../utils/notification-handler";

@Component({
  selector: 'entities',
  templateUrl: './entities.component.html',
})
export class EntitiesComponent implements OnInit {
  
  @ViewChild('editModal') editModal: AlertModal;
  @ViewChild('deleteModal') deleteModal: AlertModal;
  @ViewChild('relatedPages') relatedPages: AlertModal;
  private selectedEntities: string[] = [];
  
  public checkboxes: CheckEntity[] = [];
  
  public entities: Entity[] = [];
  
  public entityForm: UntypedFormGroup;
  
  private searchText: RegExp = new RegExp('');
  public keyword = '';
  
  public communities: Portal[] = [];
  public portal: string;
  public type: any;
	public name: string;
	public entity: CommunityInfo | Stakeholder;
  public showLogo: boolean = true;
  
  public toggleIds: string[];
  public toggleStatus: boolean;
  public properties: EnvProperties = properties;
  
  public showLoading = true;
  public isPortalAdministrator = null;
  public filterForm: UntypedFormGroup;
  private subscriptions: any[] = [];
  private index: number;
  
  constructor(private element: ElementRef, private route: ActivatedRoute,
              private _router: Router, private title: Title,
              private _helpContentService: HelpContentService,
              private userManagementService: UserManagementService, private _fb: UntypedFormBuilder,
              private communityService: CommunityService,
							private stakeholderService: StakeholderService,
              private _clearCacheService: ClearCacheService) {
  }
  
  ngOnInit() {
    this.filterForm = this._fb.group({
      keyword: [''],
      status: ['all', Validators.required]
    });
    this.subscriptions.push(this.filterForm.get('keyword').valueChanges.subscribe(value => {
      this.searchText = new RegExp(value, 'i');
      this.applyFilters();
    }));
    this.subscriptions.push(this.filterForm.get('status').valueChanges.subscribe(value => {
      this.applyFilters();
    }));
    this.userManagementService.getUserInfo().subscribe(user => {
      this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param];
      if (this.route.snapshot.data.portal) {
        this.name = StringUtils.capitalize(this.portal);
        this.title.setTitle(StringUtils.capitalize(this.portal) + ' | Entities');
      } else if (this.route.snapshot.params[this.route.snapshot.data.param]) {
        this.type = this.route.snapshot.data.param;
				if(this.route.snapshot.data.param === 'stakeholder') {
					this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
						if(stakeholder) {
							this.name = stakeholder.name;
							this.entity = stakeholder;
							this.title.setTitle(this.name + ' | Entities');
						}
					}));
				} else {
          this.subscriptions.push(this.communityService.getCommunityAsObservable().subscribe(community => {
            if(community) {
              this.showLogo = false;
              this.name = community.shortTitle;
              this.entity = community;
              this.title.setTitle(this.name + ' | Entities');
            }
          }));
				}
      } else {
        this.title.setTitle('Administrator Dashboard | Entities');
      }
      this.applyPortalFilter(this.portal);
      this.isPortalAdministrator = Session.isPortalAdministrator(user) && !this.portal;
    });
    
    
  }
  
  ngOnDestroy(): void {
    this.subscriptions.forEach(value => {
      if (value instanceof Subscriber) {
        value.unsubscribe();
      } else if (value instanceof Function) {
        value();
      }
    });
  }
  
  getEntities(portal: string) {
    this.showLoading = true;
    if (portal) {
      this._helpContentService.getCommunityEntities(portal, this.properties.adminToolsAPIURL).subscribe(
        entities => {
          this.entities = entities;
          this.checkboxes = [];
          
          let self = this;
          entities.forEach(_ => {
            self.checkboxes.push(<CheckEntity>{entity: _, checked: false});
          });
          
          this.showLoading = false;
        },
        error => this.handleError('System error retrieving entities', error));
    } else {
      this._helpContentService.getEntities(this.properties.adminToolsAPIURL).subscribe(
        entities => {
          this.entities = entities;
          this.checkboxes = [];
          
          let self = this;
          entities.forEach(_ => {
            self.checkboxes.push(<CheckEntity>{entity: _, checked: false});
          });
          this.showLoading = false;
        },
        error => this.handleError('System error retrieving entities', error));
    }
  }
  
  public toggleCheckBoxes(event) {
    this.checkboxes.forEach(_ => _.checked = event.target.checked);
  }
  
  public applyCheck(flag: boolean) {
    this.checkboxes.forEach(_ => _.checked = flag);
  }
  
  public getSelectedEntities(): string[] {
    return this.checkboxes.filter(entity => entity.checked === true).map(checkedEntity => checkedEntity.entity).map(res => res._id);
  }
  
  private deleteEntitiesFromArray(ids: string[]): void {
    for (let id of ids) {
      let i = this.entities.findIndex(_ => _._id == id);
      this.entities.splice(i, 1);
    }
    this.applyFilters();
  }
  
  public confirmDeleteEntity(id: string) {
    // this.deleteConfirmationModal.ids = [id];
    // this.deleteConfirmationModal.showModal();
    this.selectedEntities = [id];
    this.confirmDeleteEntitiesModalOpen();
  }
  
  public confirmDeleteSelectedEntities() {
    // this.deleteConfirmationModal.ids = this.getSelectedEntities();
    // this.deleteConfirmationModal.showModal();
    this.selectedEntities = this.getSelectedEntities();
    this.confirmDeleteEntitiesModalOpen();
  }
  
  private confirmDeleteEntitiesModalOpen() {
    this.deleteModal.alertTitle = 'Delete Confirmation';
    this.deleteModal.message = 'Are you sure you want to delete the selected entity(-ies)?';
    this.deleteModal.okButtonText = 'Yes';
    this.deleteModal.open();
  }
  
  public confirmedDeleteEntities(data: any) {
    this.showLoading = true;
    this._helpContentService.deleteEntities(this.selectedEntities, this.properties.adminToolsAPIURL).subscribe(
      _ => {
        this.deleteEntitiesFromArray(this.selectedEntities);
        NotificationHandler.rise('Entities have been <b>successfully deleted</b>');
        this.showLoading = false;
        // this._clearCacheService.clearCache("entities deleted");
        // this._clearCacheService.purgeBrowserCache("entities deleted", this.portal);
      },
      error => this.handleUpdateError('System error deleting the selected entities', error)
    );
  }
  
  public editEntity(i: number) {
    const entity: Entity = this.checkboxes[i].entity;
    this.index = this.entities.findIndex(value => value._id === entity._id);
    this.entityForm = this._fb.group({
      name: this._fb.control(entity.name, Validators.required),
      _id: this._fb.control(entity._id),
      pid: this._fb.control(entity.pid, Validators.required)
    });
    this.entitiesModalOpen('Edit Entity', 'Save Changes');
  }
  
  public newEntity() {
    this.entityForm = this._fb.group({
      _id: this._fb.control(null),
      name: this._fb.control('', Validators.required),
      pid: this._fb.control('', Validators.required)
    });
    this.entitiesModalOpen('Create Entity', 'Create');
  }
  
  private entitiesModalOpen(title: string, yesBtn: string) {
    this.editModal.okButtonLeft = false;
    this.editModal.alertTitle = title;
    this.editModal.okButtonText = yesBtn;
    this.editModal.open();
  }
  
  public entitySaveConfirmed(data: any) {
    this.showLoading = true;
    if (this.entityForm.getRawValue()._id) {
      this._helpContentService.updateEntity(
        <Entity>this.entityForm.getRawValue(), this.properties.adminToolsAPIURL).subscribe(
        entity => {
          this.entityUpdatedSuccessfully(entity);
          NotificationHandler.rise('Entity <b>' + entity.name + '</b> has been <b>successfully updated</b>');
          // this._clearCacheService.clearCache("entity updated");
          // this._clearCacheService.purgeBrowserCache("entity updated", this.portal);
        },
        error => this.handleUpdateError('System error updating entity', error)
      );
    } else {
      this._helpContentService.saveEntity(<Entity>this.entityForm.getRawValue(), this.properties.adminToolsAPIURL).subscribe(
        entity => {
          this.entitySavedSuccessfully(entity);
          NotificationHandler.rise('Entity <b>' + entity.name + '</b> has been <b>successfully created</b>');
          // this._clearCacheService.clearCache("entity saved");
          // this._clearCacheService.purgeBrowserCache("entity saved", this.portal)
        },
        error => this.handleUpdateError('System error creating entity', error)
      );
    }
  }
  
  
  public entitySavedSuccessfully(entity: Entity) {
    this.entities.push(entity);
    this.applyFilters();
    this.applyCheck(false);
    this.showLoading = false;
  }
  
  public entityUpdatedSuccessfully(entity: Entity) {
    this.entities[this.index] = entity;
    this.applyFilters();
    this.applyCheck(false);
    this.showLoading = false;
  }
  
  public applyFilters() {
    this.checkboxes = [];
    this.entities.filter(item => this.filterEntitiesByStatus(item)).forEach(
      _ => this.checkboxes.push(<CheckEntity>{entity: _, checked: false})
    );
    this.checkboxes = this.checkboxes.filter(item => this.filterEntities(item.entity));
  }
  
  public filterEntities(entity: Entity): boolean {
    const textFlag = this.searchText.toString() === '' || (entity.name).match(this.searchText) != null;
    return textFlag;
  }
  
  public filterEntitiesByStatus(entity: Entity): boolean {
    let status = this.filterForm.get("status").value;
    return status == "all" || (status == "disabled" && !entity.isEnabled) || (status == "enabled" && entity.isEnabled);
  }
  
  handleError(message: string, error = null) {
    if(error) {
      console.log('Server responded: ' + error);
    }
    NotificationHandler.rise(message, 'danger');
    this.showLoading = false;
  }
  
  handleUpdateError(message: string, error = null) {
    if (!error) {
      this.entityForm = this._fb.group({
        pid: ['', Validators.required],
        name: ['', Validators.required],
        isEnabled: '',
        _id: ''
      });
    } else {
      console.log('Server responded: ' + error);
    }
    NotificationHandler.rise(message, 'danger');
    this.showLoading = false;
  }
  
  public applyPortalFilter(portal: string) {
    this.getEntities(portal);
  }
  
  public toggleEntities(status: boolean, ids: string[]) {
    // this.okModal.showModal();
    this.toggleIds = ids;
    this.toggleStatus = status;
    this.confirmRelatedPagesModalOpen();
  }
  
  private confirmRelatedPagesModalOpen() {
    this.relatedPages.alertTitle = 'Warning';
    this.relatedPages.message = "This action will affect all search pages related to this entity! Pages' status will change to entity's status! Do you want to continue?";
    this.relatedPages.okButtonText = 'Yes';
    this.relatedPages.open();
  }
  
  public continueToggling(event: any) {
    this._helpContentService.toggleEntities(
      this.portal, this.toggleIds, this.toggleStatus, this.properties.adminToolsAPIURL).subscribe(
      () => {
        for (let id of this.toggleIds) {
          const i = this.checkboxes.findIndex(_ => _.entity._id === id);
          this.checkboxes[i].entity.isEnabled = this.toggleStatus;
        }
        this.applyCheck(false);
        this._clearCacheService.clearCacheInRoute("entity's status changed", this.portal, "/");
        this._clearCacheService.purgeBrowserCache("entity's status changed", this.portal);
      },
      error => this.handleUpdateError('System error changing the status of the selected entity(-ies)', error)
    );
  }
  
  selectAll() {
    let checked = (this.getSelectedEntities().length != this.checkboxes.length);
    for (let check of this.checkboxes) {
      check.checked = checked;
    }
  }
}
