import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Title} from '@angular/platform-browser';
import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties';
import {Category, Stakeholder, SubCategory, Topic} from "../utils/entities/stakeholder";
import {StakeholderService} from "../services/stakeholder.service";
import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class";
import {AlertModal} from "../openaireLibrary/utils/modal/alert";
import {Subscriber} from "rxjs";
import {FormBuilder, FormGroup, Validators} from "@angular/forms";
import {IndicatorUtils} from "../utils/indicator-utils";

declare var UIkit;

@Component({
  selector: 'topic',
  templateUrl: './topic.component.html',
})
export class TopicComponent implements OnInit, OnDestroy {
  public subscriptions: any[] = [];
  public properties: EnvProperties;
  public indicatorUtils: IndicatorUtils = new IndicatorUtils();
  public loading: boolean = true;
  public stakeholder: Stakeholder;
  /**
   * Current topic
   **/
  public topicIndex: number = 0;
  public topicFb: FormGroup;

  /**
   * categoryIndex: Current category to be edited, selectedCategoryIndex: selected on menu(opened)
   */
  public categoryIndex: number = 0;
  public selectedCategoryIndex: number = 0;
  public categoryFb: FormGroup;
  /**
   * Current Subcategory to be edited
   */
  public subCategoryIndex: number = 0;
  public subcategoryFb: FormGroup;
  /**
   * Current drop element and index of topic, category or subcategory to be deleted.
   */
  public element: any;
  public index: number;
  /**
   * Check form validity
   */
  public toggle: boolean = false;

  @ViewChild('deleteTopicModal') deleteTopicModal: AlertModal;
  @ViewChild('deleteCategoryModal') deleteCategoryModal: AlertModal;
  @ViewChild('deleteSubcategoryModal') deleteSubcategoryModal: AlertModal;

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private title: Title,
    private fb: FormBuilder,
    private stakeholderService: StakeholderService) {
  }

  public ngOnInit() {
    this.route.data
      .subscribe((data: { envSpecific: EnvProperties }) => {
        this.properties = data.envSpecific;
        this.route.params.subscribe( params => {
          this.subscriptions.push(this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => {
            if (stakeholder) {
              this.stakeholder = HelperFunctions.copy(stakeholder);
              this.topicIndex = this.stakeholder.topics.findIndex(topic => topic.alias === params['topic']);
              if(this.topicIndex === -1) {
                this.navigateToError();
              } else {
                this.title.setTitle(stakeholder.index_shortName + ' | ' + this.stakeholder.topics[this.topicIndex].name);
                this.toggle = true;
              }
            }
          }));
        });
      });
  }

  public ngOnDestroy() {
    this.subscriptions.forEach( value => {
      if(value instanceof Subscriber) {
        value.unsubscribe();
      }
    });
  }

  public hide(element) {
    UIkit.drop(element).hide();
  }

  public show(element) {
    UIkit.drop(element).show();
  }

  private buildTopic(topic: Topic) {
    this.topicFb = this.fb.group({
      _id: this.fb.control(topic._id),
      name: this.fb.control(topic.name, Validators.required),
      description: this.fb.control(topic.description),
      alias: this.fb.control(topic.alias),
      isActive: this.fb.control(topic.isActive),
      isPublic: this.fb.control(topic.isPublic),
      isDefault: this.fb.control(topic.isDefault),
      categories: this.fb.control(topic.categories)
    });
  }

  public editTopicOpen(element) {
    if(element.className.indexOf('uk-open') !== -1) {
      this.hide(element);
    } else {
      this.buildTopic(this.stakeholder.topics[this.topicIndex]);
      this.show(element);
    }
  }

  public saveTopic(element) {
    if(!this.topicFb.invalid) {
      if(!this.topicFb.value.alias) {
        this.topicFb.value.alias = this.topicFb.value.name.toLowerCase().trim();
      }
      let path = [this.stakeholder._id];
      let callback = (topic: Topic): void => {
          this.stakeholder.topics[this.topicIndex] = topic;
          this.stakeholderService.setStakeholder(this.stakeholder);
      };
      this.save('Topic has been successfully saved', element, path, this.topicFb.value, callback,true);
    }
  }

  public deleteTopicOpen(name: string, element) {
    this.deleteOpen(name,'topic', this.deleteTopicModal, element, this.topicIndex);
  }

  public deleteTopic() {
    let path: string[] = [
      this.stakeholder._id,
      this.stakeholder.topics[this.topicIndex]._id
    ];
    let callback = (): void => {
      this.stakeholder.topics.splice(this.topicIndex, 1);
      this.stakeholderService.setStakeholder(this.stakeholder);
    };
    this.delete('Topic has been successfully be deleted', path, callback, true);
  }

  public toggleCategory(index: number) {
   if(this.selectedCategoryIndex !== index) {
      this.selectedCategoryIndex = index;
      this.toggle = true;
    } else {
      this.toggle = !this.toggle;
    }
  }

  private buildCategory(category: Category) {
    this.categoryFb = this.fb.group({
      _id: this.fb.control(category._id),
      name: this.fb.control(category.name, Validators.required),
      alias: this.fb.control(category.alias),
      isActive: this.fb.control(category.isActive),
      isPublic: this.fb.control(category.isPublic),
      isDefault: this.fb.control(category.isDefault),
      subCategories: this.fb.control(category.subCategories)
    });
  }

  public editCategoryOpen(element, index:number = -1) {
    if(element.className.indexOf('uk-open') !== -1) {
      this.hide(element);
    } else {
      if(index === -1) {
        this.buildCategory(new Category(null, null, null, true, true));
      } else {
        this.buildCategory(this.stakeholder.topics[this.topicIndex].categories[index]);
      }
      this.show(element);
    }
  }

  public saveCategory(element, index = -1) {
    if(!this.categoryFb.invalid) {
      if(!this.categoryFb.value.alias) {
        this.categoryFb.value.alias = this.categoryFb.value.name.toLowerCase();
      }
      let path = [this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id];
      let callback = (category: Category): void => {
        if(index === -1) {
          this.stakeholder.topics[this.topicIndex].categories.push(category);
        } else {
          this.stakeholder.topics[this.topicIndex].categories[index] = HelperFunctions.copy(category);
        }
        this.stakeholderService.setStakeholder(this.stakeholder);
      };
      if(index === -1) {
        this.save('Category has been successfully created', element, path, this.categoryFb.value, callback);
      } else {
        this.save('Category has been successfully saved', element, path, this.categoryFb.value, callback);
      }
    }
  }

  public deleteCategoryOpen(name: string, element, index) {
    this.deleteOpen(name,'category', this.deleteCategoryModal, element, index);
  }

  public deleteCategory() {
    let path: string[] = [
      this.stakeholder._id,
      this.stakeholder.topics[this.topicIndex]._id,
      this.stakeholder.topics[this.topicIndex].categories[this.index]._id
    ];
    let callback = (): void => {
      this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1);
      this.stakeholderService.setStakeholder(this.stakeholder);
    };
    this.delete('Category has been successfully be deleted', path, callback);
  }

  private buildSubcategory(subCategory: SubCategory) {
    this.subcategoryFb = this.fb.group({
      _id: this.fb.control(subCategory._id),
      name: this.fb.control(subCategory.name, Validators.required),
      alias: this.fb.control(subCategory.alias),
      isActive: this.fb.control(subCategory.isActive),
      isPublic: this.fb.control(subCategory.isPublic),
      isDefault: this.fb.control(subCategory.isDefault),
      charts: this.fb.control(subCategory.charts),
      numbers: this.fb.control(subCategory.numbers)
    });
  }

  public editSubCategoryOpen(element, index:number = -1) {
    if(element.className.indexOf('uk-open') !== -1) {
      this.hide(element);
    } else {
      if(index === -1) {
        this.buildSubcategory(new SubCategory(null, null, null, true, true));
      } else {
        this.buildSubcategory(this.stakeholder.topics[this.topicIndex].
          categories[this.selectedCategoryIndex].subCategories[index]);
      }
      this.show(element);
    }
  }

  public saveSubCategory(element, index = -1) {
    if(!this.subcategoryFb.invalid) {
      if(!this.subcategoryFb.value.alias) {
        this.subcategoryFb.value.alias = this.subcategoryFb.value.name.toLowerCase();
      }
      let path: string[] = [
        this.stakeholder._id,
        this.stakeholder.topics[this.topicIndex]._id,
        this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
      ];
      let callback = (subCategory: SubCategory): void => {
        if(index === -1) {
          this.stakeholder.topics[this.topicIndex].
            categories[this.selectedCategoryIndex].subCategories.push(subCategory);
        } else {
          this.stakeholder.topics[this.topicIndex].
            categories[this.selectedCategoryIndex].subCategories[index] = subCategory;
        }
        this.stakeholderService.setStakeholder(this.stakeholder);
      };
      if(index === -1) {
        this.save('Subcategory has been successfully created', element, path, this.subcategoryFb.value, callback);
      } else {
        this.save('Subcategory has been successfully saved', element, path, this.subcategoryFb.value, callback);
      }
      this.hide(element);
    }
  }

  public deleteSubcategoryOpen(name: string, element, index) {
    this.deleteOpen(name,'subcategory', this.deleteSubcategoryModal, element, index);
  }

  public deleteSubcategory() {
    let path: string[] = [
      this.stakeholder._id,
      this.stakeholder.topics[this.topicIndex]._id,
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id,
      this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id
    ];
    let callback = (): void => {
      this.stakeholder.topics[this.topicIndex].
        categories[this.selectedCategoryIndex].subCategories.splice(this.index, 1);
      this.stakeholderService.setStakeholder(this.stakeholder);
    };
    this.delete('Subcategory has been successfully be deleted', path, callback);
  }

  private navigateToError() {
    this.router.navigate(['/error'], {queryParams: {'page': this.router.url}});
  }

  private deleteOpen(name: string, type: string, modal: AlertModal, element, index) {
    this.element = element;
    this.index = index;
    modal.alertTitle = 'Delete ' + name;
    modal.cancelButtonText = 'No';
    modal.okButtonText = 'Yes';
    modal.message = 'This ' + type + ' will permanently be deleted. Are you sure you want to proceed?';
    modal.open();
  }

  private save(message: string, element, path: string[], saveElement: any, callback: Function, redirect = false) {
    this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => {
      callback(saveElement);
      UIkit.notification(message, {
        status: 'success',
        timeout: 3000,
        pos: 'top-left'
      });
      if(redirect) {
        this.router.navigate(['../' + saveElement.alias], {
          relativeTo: this.route
        });
      }
      this.hide(element);
    }, error => {
      UIkit.notification(error.error.message, {
        status: 'danger',
        timeout: 3000,
        pos: 'top-left'
      });
      this.hide(element);
    });
  }

  private delete(message: string, path: string[], callback: Function, redirect = false) {
    this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path).subscribe(() => {
      callback();
      UIkit.notification(message, {
        status: 'success',
        timeout: 3000,
        pos: 'top-left'
      });
      if(redirect) {
        this.back();
      }
      this.hide(this.element);
    }, error => {
      UIkit.notification(error.error.message, {
        status: 'danger',
        timeout: 3000,
        pos: 'top-left'
      });
      this.hide(this.element);
    });
  }

  back() {
    this.router.navigate(['../'], {
      relativeTo: this.route
    });
  }

  chooseSubcategory(categoryIndex: number, subcategoryIndex: number) {
    this.categoryIndex = categoryIndex;
    this.subCategoryIndex = subcategoryIndex;
  }
}
