import {ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {HelpContentService} from '../../services/help-content.service';
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
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, Subscription} from "rxjs";
import {properties} from "../../../../environments/environment";
import {StringUtils} from "../../utils/string-utils.class";
import {Title} from "@angular/platform-browser";
import {AlertModal} from '../../utils/modal/alert';
import {MenuAlignment, MenuItemExtended} from '../../sharedComponents/menu';
import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component';
import {Option} from '../../sharedComponents/input/input.component';
import {CommunityInfo} from '../../connect/community/communityInfo';
import {Stakeholder} from '../../monitor/entities/stakeholder';
import {StakeholderService} from '../../monitor/services/stakeholder.service';
import {CommunityService} from '../../connect/community/community.service';
import {ClearCacheService} from '../../services/clear-cache.service';
import {TransitionGroupComponent} from '../../utils/transition-group/transition-group.component';
import {HelperFunctions} from '../../utils/HelperFunctions.class';
import {NotificationHandler} from '../../utils/notification-handler';
// import {Page} from "../../utils/entities/adminTool/page";

declare var UIkit;

@Component({
  selector: 'menuSelector',
  templateUrl: './menu.component.html',
	styleUrls: ['./menu.component.less']
})
export class MenuComponent implements OnInit {
	
	@ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent;
	@ViewChild('editModal') editModal: AlertModal;
	@ViewChild('deleteModal') deleteModal: AlertModal;
	@ViewChild("elements") elements: TransitionGroupComponent;
	@ViewChild("subElements") subElements: TransitionGroupComponent;

	private index: number;

  // public newPageWindowOpen: boolean = false;

  public menuItemForm: FormGroup;
	public pageForm: FormGroup;
	public menuTypes = [
		{label: 'Normal Menu', value: 'normalMenu'},
		{label: 'Custom Menu', value: 'customMenu'}
	];
	public selectedMenuType = this.menuTypes[0].value;
	public normalMenuItems: MenuItemExtended[] = [];
	public featuredMenuItems: MenuItemExtended[] = [];
	public allPages = [];
	public parentOptions: Option[] = [];
	public pageStatus: Map<string,boolean> = null;

	public selectedMenuItem: string;
	public selectedMenuItemParent: string;
	public isChild: boolean = false;

	public showNormalMenu: boolean = false;
	public showFeaturedMenu: boolean = false;
	public featuredAlignment: string = MenuAlignment.CENTER.valueOf();

  public communities: Portal[] = [];
  public portal: string;
	public name: string;
	public entity: CommunityInfo | Stakeholder;
  public showLogo: boolean = true;
	public type: any;
  
  public showLoading = true;
  public isPortalAdministrator = null;
  public filterForm: FormGroup;
	public typeOptions: Option[] = [
		{label: 'Internal page', value: 'internal'},
		{label: 'External URL', value: 'external'},
	]
	public rootOnlyTypeOptions: Option[] = [
		{label: 'No Action', value: 'noAction'}
	]

	public properties: EnvProperties = properties;
  private subscriptions: any[] = [];
	private typeSub: Subscription = null;
  
  constructor(private route: ActivatedRoute,
              private title: Title,
              private _helpContentService: HelpContentService,
              private userManagementService: UserManagementService, private _fb: FormBuilder,
							private stakeholderService: StakeholderService,
							private communityService: CommunityService,
							private _clearCacheService: ClearCacheService,
							private cdr: ChangeDetectorRef) {
  }
  
  ngOnInit() {
    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];
			this.getMenuItems();
      if (this.route.snapshot.data.portal) {
				this.name = StringUtils.capitalize(this.portal);
        this.title.setTitle(StringUtils.capitalize(this.portal) + ' | Menu');
      } 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 + ' | Menu');
						}
					}));
				} 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 + ' | Menu');
						}
					}));
				}
      } else {
        this.title.setTitle('Administrator Dashboard | Menu');
      }
      this.isPortalAdministrator = Session.isPortalAdministrator(user);
			this.selectedMenuType = this.isPortalAdministrator ? this.menuTypes[0].value : this.menuTypes[1].value;
    });
  }
  
  ngOnDestroy(): void {
    this.subscriptions.forEach(value => {
      if (value instanceof Subscriber) {
        value.unsubscribe();
      } else if (value instanceof Function) {
        value();
      }
    });
		this.destroyTypeSubscription();
  }

	destroyTypeSubscription() {
		if(this.typeSub instanceof Subscriber) {
			this.typeSub.unsubscribe();
		}
	}

	getMenuItems() {
		this.subscriptions.push(
			this._helpContentService.getMenuItems(this.portal).subscribe(
				data => {
					this.featuredMenuItems = data.featuredMenuItems;
					this.normalMenuItems = data.menuItems;
					this.showFeaturedMenu = data.isFeaturedMenuEnabled;
					this.showNormalMenu = data.isMenuEnabled;
          this.featuredAlignment = data.featuredAlignment.valueOf();
					this.getPages();
					this.getParentOptions();
					this.showLoading = false;
				},
				error => this.handleError("Server error fetching menu items", error)
			)
		);
	}

	getTypeOptions(isFeatured: boolean = false, parentItem) {
		if(this.isChild || parentItem != '') {
			return this.typeOptions;
		} else {
			if(isFeatured || !this.isPortalAdministrator) {
				return this.typeOptions;
			} else {
				return this.typeOptions.concat(this.rootOnlyTypeOptions);
			}
		}
	}

	getPages() {
		this.subscriptions.push(
			this._helpContentService.getCommunityPagesByType(this.portal, '', this.properties.adminToolsAPIURL).subscribe(
				data => {
					let pages = data;
					this.pageStatus = new Map();
					for(let i = 0; i < pages.length; i++) {
						if(pages[i] && pages[i].name && pages[i].route) {
							this.allPages.push({value: pages[i].route, label: pages[i].name + (pages[i].isEnabled ? '' : ' [disabled]'), isEnabled: pages[i].isEnabled});
							this.pageStatus.set(pages[i].route, pages[i].isEnabled);
						}
					}
				},
				error => this.handleError("Server error fetching pages", error)
			)
		);
	}

	getParentOptions() {
		this.parentOptions = this.normalMenuItems.map(item => ({label: item.title, value: item._id}));
		this.parentOptions.unshift({label: 'No parent', value: ''});
	}

	addValidatorForUrlOrRoute() {
		this.destroyTypeSubscription();
		this.typeSub = this.menuItemForm.get('type').valueChanges.subscribe(value => {
			setTimeout(() => {
				this.menuItemForm.controls['route'].clearValidators();
				this.menuItemForm.controls['url'].clearValidators();
				if(value === "internal") {
					this.menuItemForm.controls['route'].setValidators([Validators.required]);
				} else if(value === "external") {
					this.menuItemForm.controls['url'].setValidators([Validators.required, StringUtils.urlValidator()]);
				}
				this.menuItemForm.controls['route'].updateValueAndValidity();
				this.menuItemForm.controls['url'].updateValueAndValidity();
			}, 0);
		});
	}

	public newMenuItem() {
		this.menuItemForm = this._fb.group({
			_id: this._fb.control(""),
			title: this._fb.control("",Validators.required),
			type: this._fb.control("",Validators.required),
      route: this._fb.control(""),
			url: this._fb.control(""),
      isEnabled: this._fb.control(""),
			isFeatured: this._fb.control(this.selectedMenuType == 'customMenu'),
			parentItemId: this._fb.control("")
		});
		this.addValidatorForUrlOrRoute();
		this.menuItemsModalOpen('Add Menu Item', 'Create');
	}

	public editMenuItem(index: number, menuItem: MenuItemExtended, isChild: boolean = false) {
		this.menuItemForm = this._fb.group({
			_id: this._fb.control(menuItem['_id']),
			title: this._fb.control(menuItem.title,Validators.required),
			type: this._fb.control(menuItem['type'],Validators.required),
      route: this._fb.control(menuItem.route, (menuItem['type'] == "internal") ? [Validators.required] : []),
			url: this._fb.control(menuItem.url, (menuItem['type'] == "external") ? [Validators.required, StringUtils.urlValidator()] : []),
			isFeatured: this._fb.control(menuItem.isFeatured),
			parentItemId: this._fb.control(menuItem.parentItemId)
		});
		this.isChild = isChild;
		this.index = index;
		this.addValidatorForUrlOrRoute();
		this.menuItemsModalOpen('Edit Menu Item', 'Save Changes');
	}

	public confirmDeleteMenuItem(id: string, isChild: boolean = false, parentId: string) {
		this.selectedMenuItemParent = parentId;
		this.selectedMenuItem = id;
		this.isChild = isChild;
		this.confirmModalOpen();
	}

	private confirmModalOpen() {
    this.deleteModal.alertTitle = 'Delete Confirmation';
    this.deleteModal.message = 'Are you sure you want to delete this menu item?';
    this.deleteModal.okButtonText = 'Yes';
    this.deleteModal.open();
  }

	public confirmedDeleteMenuItem(data: any) {
		this.showLoading = true;
		this.subscriptions.push(
			this._helpContentService.deleteMenuItem(this.selectedMenuItem, this.portal).subscribe(
				_ => {
					this.deleteMenuItemFromArray(this.selectedMenuItem, this.isChild);
					NotificationHandler.rise("Menu item have been <b>successfully deleted</b>");
					this.showLoading = false;
					this._clearCacheService.clearCacheInRoute("Menu item deleted",this.portal, "/");

				},
				error => this.handleError("Server error deleting menu item", error)
			)
		)
	}

	private deleteMenuItemFromArray(id: string, isChild: boolean = false) {
		if(isChild) {
			let i = this.normalMenuItems.findIndex(_ => _._id == this.selectedMenuItemParent);
			let j = this.normalMenuItems[i].items.findIndex(_ => _._id == id);
			this.normalMenuItems[i].items.splice(j, 1);
		} else {
			if(this.selectedMenuType == 'customMenu') {
				let i = this.featuredMenuItems.findIndex(_ => _._id == id);
				this.featuredMenuItems.splice(i, 1);
			} else {
				let i = this.normalMenuItems.findIndex(_ => _._id == id);
				this.normalMenuItems.splice(i, 1);
				this.getParentOptions();
			}
		}
	}

	private menuItemsModalOpen(title: string, yesBtn: string) {
		this.editModal.okButtonLeft = false;
		this.editModal.alertTitle = title;
		this.editModal.okButtonText = yesBtn;
		this.editModal.open();
	}

	public menuItemSaveConfirmed(data: any) {
		this.destroyTypeSubscription();
		this.showLoading = true;
    this.menuItemForm.value.target = this.menuItemForm.value['type'] == "internal" ? "_self" : "_blank";
    if(!this.menuItemForm.value._id) {
			this.subscriptions.push(
				this._helpContentService.saveMenuItem(<MenuItemExtended>this.menuItemForm.getRawValue(), this.portal).subscribe(
					menuItem => {
						this.menuItemSavedSuccessfully(menuItem, true);
						NotificationHandler.rise('Menu item <b>' + menuItem.title + '</b> has been <b>successfully created</b>');
						this._clearCacheService.clearCacheInRoute("Menu item saved",this.portal, "/");
					},
					error => this.handleError("System error creating menu item", error)
				)
			)
		} else {
			this.subscriptions.push(
				this._helpContentService.updateMenuItem(<MenuItemExtended>this.menuItemForm.getRawValue(), this.portal).subscribe(
					menuItem => {
						this.menuItemSavedSuccessfully(menuItem, false);
						NotificationHandler.rise('Menu item <b>' + menuItem.title + '</b> has been <b>successfully updated</b>');
						this._clearCacheService.clearCacheInRoute("Menu item updated",this.portal, "/");
					},
					error => this.handleError("System error updating menu item", error)
				)
			)
		}
	}

	public menuItemSavedSuccessfully(menuItem: MenuItemExtended, isNew: boolean) {
		if(isNew) {
			if(menuItem.parentItemId) {
				let i = this.normalMenuItems.findIndex(_ => _._id == menuItem.parentItemId);
				this.normalMenuItems[i].items.push(menuItem);
			} else {
				if(menuItem.isFeatured) {
					this.featuredMenuItems.push(menuItem);
				} else {
					this.normalMenuItems.push(menuItem);
					this.getParentOptions();
				}
			}
		} else {
			if(menuItem.parentItemId) {
			} else {
				if(menuItem.isFeatured) {
					this.featuredMenuItems[this.index] = menuItem;
				} else {
					this.normalMenuItems[this.index] = menuItem;
					this.getParentOptions();
				}
			}
		}
		this.showLoading = false;
	}

	handleError(message: string, error) {
		NotificationHandler.rise(message, 'danger');
		console.log('Server responded: ' + error);
		this.showLoading = false;
	}

	public toggleMenuItem(menuItem) {
		menuItem.isOpen = !menuItem.isOpen;
	}

	public valueChange() {
		this.cdr.detectChanges();
		this.elements.init();
	}

	public get displayMenuItems() {
		return this.selectedMenuType == 'customMenu' ? this.featuredMenuItems : this.normalMenuItems;
	}

	public moveElement(index: number, newIndex: number, children: MenuItemExtended[] = []) {
		this.elements.init();
		if(children && children.length) {
			this.subElements.init();
		}
		if(this.selectedMenuType == 'customMenu') {
			let temp = HelperFunctions.copy(this.featuredMenuItems);
			HelperFunctions.swap(temp, index, newIndex);
			this._helpContentService.reorderMenuItems(temp, this.portal).subscribe(() => {
				HelperFunctions.swap(this.featuredMenuItems, index, newIndex);
				this._clearCacheService.clearCacheInRoute("Menu items reordered",this.portal, "/");
			}, error => {
				this.handleError("System error reordering menu items", error);
			});
		} else {
			let temp = HelperFunctions.copy(this.normalMenuItems);
			if(children && children.length) {
				temp = HelperFunctions.copy(children);
			}
			HelperFunctions.swap(temp, index, newIndex);
			this._helpContentService.reorderMenuItems(temp, this.portal).subscribe(() => {
				HelperFunctions.swap(children && children.length ? children : this.normalMenuItems, index, newIndex);
				this._clearCacheService.clearCacheInRoute("Menu items reordered",this.portal, "/");
			}, error => {
				this.handleError("System error reordering menu items", error);
			});
		}
	}

	public toggleMenu(status: boolean, isFeatured: boolean) {
		this.subscriptions.push(
			this._helpContentService.toggleMenu(status, isFeatured, this.portal).subscribe(() => {
				if(isFeatured) {
					this.showFeaturedMenu = status;
				} else {
					this.showNormalMenu = status;
				}
				this._clearCacheService.clearCacheInRoute("Menu toggled",this.portal, "/");
        NotificationHandler.rise("Menu has been <b>successfully toggled to be "+(status?"visible":"hidden")+"</b>");
      }, error => {
				this.handleError("System error toggling menu", error);
			})
		);
	}

  public alignMenu(alignment: string) {
    this.subscriptions.push(
      this._helpContentService.alignMenu(MenuAlignment[alignment], this.portal).subscribe(() => {
        this.featuredAlignment = alignment;
        this._clearCacheService.clearCacheInRoute("Menu aligned",this.portal, "/");
        NotificationHandler.rise("Menu has been <b>successfully "+alignment.toLowerCase()+" aligned</b>");
      }, error => {
        this.handleError("System error aligning menu to the "+alignment.toLowerCase(), error);
      })
    );
  }

  // public newPageWindow() {
  //   this.newPageWindowOpen = !this.newPageWindowOpen;
  //   this.pageForm = this._fb.group({
  //     _id: this._fb.control(null),
  //     route: this._fb.control('/featured/', [Validators.required, StringUtils.validRoute(this.allPages, 'value'), this.validCustomRoute()]),
  //     name: this._fb.control('', Validators.required),
  //     isEnabled: this._fb.control(true),
  //     portalType: this._fb.control(this.properties.adminToolsPortalType, Validators.required),
  //     portalPid: this._fb.control(this.portal),
  //     top: this._fb.control(true),
  //     bottom: this._fb.control(false),
  //     left: this._fb.control(false),
  //     right: this._fb.control(false),
  //     type: this._fb.control('html', Validators.required),
  //     entities: this._fb.control([''])
  //   });
  // }
  //
  // public validCustomRoute(): ValidatorFn {
  //   return (control: AbstractControl): ValidationErrors | null => {
  //     if (control.value) {
  //       if (!control.value.startsWith("/featured")) {
  //         return {error: 'Custom route should start with /featured'}
  //       }
  //     }
  //   }
  // }
  //
  // public createPage() {
  //   if(!this.pageForm.value.route.startsWith('/featured')) {
  //     this.pageForm.value.route = '/featured/'.concat(this.pageForm.value.route);
  //   }
  //
  //   this.showLoading = true;
  //   this.subscriptions.push(
  //     this._helpContentService.savePage(<Page>this.pageForm.value, this.properties.adminToolsAPIURL).subscribe(
  //       page => {
  //         this.allPages.push({value: page.route, label: page.name});
  //         NotificationHandler.rise('Page <b>' + page.name + '</b> has been <b>successfully created</b>');
  //         this.newPageWindowOpen = !this.newPageWindowOpen;
  //         this.menuItemForm.get('route').setValue(page.route);
  //         this.menuItemForm.get('route').markAsDirty();
  //         this.showLoading = false;
  //       },
  //       error => this.handleError('System error creating page', error)
  //     )
  //   );
  // }
}
