import {SafeResourceUrl} from "@angular/platform-browser";
import {Session, User} from "../../login/utils/helper.class";
import {StringUtils} from "../../utils/string-utils.class";

export const ChartHelper = {
  prefix: "((__",
  suffix: "__))"
};

export type StakeholderType = 'funder' | 'ri' | 'project' | 'organization' | 'country' | 'researcher' | 'datasource';
export type IndicatorType = 'number' | 'chart';
export type IndicatorSize = 'small' | 'medium' | 'large';
export type IndicatorPathType = 'table' | 'bar' | 'column' | 'pie' | 'line' | 'other';
export type SourceType = 'statistics' | 'search' |'stats-tool' | 'old' | 'image';
export type Format = 'NUMBER' | 'PERCENTAGE';
export type Visibility = 'PUBLIC' | 'PRIVATE' | 'RESTRICTED';
export type Overlay = 'embed' | 'description' | false;

export class Stakeholder {
  _id: string;
  type: StakeholderType;
  funderType: string;
  name: string;
  index_id;
  index_name: string;
  index_shortName: string;
  statsProfile: string = "monitor";
  locale: string = 'eu';
  alias: string;
  defaultId: string;
  visibility: Visibility;
  creationDate: Date = null;
  updateDate: Date;
  projectUpdateDate: Date;
  /** @warning Use pipe in HTML or StringUtils.getLogoUrl in components */
  logoUrl: string;
  isUpload: boolean = false;
  description: string;
  topics: any[];
  details?: any;
  
  constructor(_id: string, type: StakeholderType, index_id: string, index_name: string, index_shortName: string, alias: string, visibility: Visibility, logoUrl: string, defaultId: string = null, description: string = null) {
    this._id = _id;
    this.type = type;
    this.index_id = index_id;
    this.index_name = index_name;
    this.index_shortName = index_shortName;
    this.defaultId = defaultId;
    this.alias = alias;
    this.visibility = visibility;
    this.logoUrl = logoUrl;
    this.description = description;
    this.topics = [];
  }

  static checkIsUpload(response: Stakeholder | Stakeholder[]): any | any[] {
    if (Array.isArray(response)) {
      response.forEach(value => {
        value.isUpload = value.logoUrl && !StringUtils.isValidUrl(value.logoUrl);
      });
    } else {
      response.isUpload = response.logoUrl && !StringUtils.isValidUrl(response.logoUrl);
    }
    return response;
  }
}

export class StakeholderInfo extends Stakeholder {
  isManager: boolean = false;
  isMember: boolean = false;
  
  public static toStakeholderInfo(stakeholders: (Stakeholder & StakeholderInfo)[], user: User): StakeholderInfo[] {
    return stakeholders.map(stakeholder => {
      stakeholder.isManager = Session.isPortalAdministrator(user) || Session.isMonitorCurator(user) || Session.isManager(stakeholder.type, stakeholder.alias, user);
      stakeholder.isMember = Session.isMember(stakeholder.type, stakeholder.alias, user);
      return stakeholder;
    })
  }
}

export class Topic {
  _id: string;
  name: string;
  alias: string;
  description: string;
  visibility: Visibility;
  creationDate: Date = null;
  updateDate: Date;
  defaultId: string;
  categories: Category[];
  icon: string;
  
  constructor(name: string, description: string, alias: string, visibility:Visibility, defaultId: string = null, icon: string = null) {
    this._id = null;
    this.name = name;
    this.description = description;
    this.alias = alias;
    this.visibility = visibility;
    this.defaultId = defaultId;
    this.categories = [];
    this.icon = icon;
  }
}

export class Category {
  _id: string;
  name: string;
  alias: string;
  description: string;
  creationDate: Date = null;
  updateDate: Date;
  visibility: Visibility;
  defaultId: string;
  subCategories: SubCategory[];
  
  constructor(name: string, description: string, alias: string, visibility: Visibility, defaultId: string = null) {
    this._id = null;
    this.name = name;
    this.description = description;
    this.alias = alias;
    this.visibility = visibility;
    this.defaultId = defaultId;
    this.subCategories = [];
  }
}

export class SubCategory {
  _id: string;
  name: string;
  alias: string;
  description: string;
  creationDate: Date = null;
  updateDate: Date;
  visibility: Visibility;
  defaultId: string;
  charts: Section[];
  numbers: Section[];

  constructor(name: string, description: string, alias: string, visibility: Visibility, defaultId: string = null) {
    this._id = null;
    this.name = name;
    this.description = description;
    this.alias = alias;
    this.visibility = visibility;
    this.defaultId = defaultId;
    this.charts = [];
    this.numbers = [];
  }
  
}

export class Section {
  _id: string;
  title: string;
  defaultId: string;
  creationDate: Date = null;
  updateDate: Date;
  stakeholderAlias: string;
  type: IndicatorType;
  indicators: Indicator[];
  
  constructor(type: IndicatorType, title: string = null, defaultId: string = null, stakeholderAlias: string = null) {
    this._id = null;
    this.title = title;
    this.type = type;
    this.defaultId = defaultId;
    this.stakeholderAlias = stakeholderAlias;
    this.indicators = [];
  }
}

export class Indicator {
  _id: string;
  name: string;
  description: string;
  additionalDescription: string;
  creationDate: Date = null;
  updateDate: Date;
  type: IndicatorType;
  width: IndicatorSize;
  height: IndicatorSize;
  tags: string[];
  visibility: Visibility;
  defaultId: string;
  indicatorPaths: IndicatorPath[];
  activePath: number = 0;
  overlay: Overlay = false;

  constructor(name: string, description: string, additionalDescription:string, type: IndicatorType, width: IndicatorSize,height: IndicatorSize, visibility: Visibility, indicatorPaths: IndicatorPath[], defaultId: string = null) {
    this._id = null;
    this.name = name;
    this.description = description;
    this.additionalDescription = additionalDescription;
    this.type = type;
    this.width = width;
    this.height = height;
    this.visibility = visibility;
    this.defaultId = defaultId;
    this.indicatorPaths = indicatorPaths;
  }
  
}

export class IndicatorPath {
  type: IndicatorPathType;
  source: SourceType;
  url: string;
  safeResourceUrl: SafeResourceUrl; // initialize on front end
  jsonPath: string[];
  chartObject: string;
  parameters: any;
  filters: any;
  filtersApplied: number = 0;
  format: Format;
  
  constructor(type: IndicatorPathType, source: SourceType, url: string, chartObject: string, jsonPath: string[], format: Format = 'NUMBER') {
    this.type = type;
    this.url = url;
    this.source = source;
    this.jsonPath = jsonPath;
    this.chartObject = chartObject;
    this.parameters = {};
    this.filters = {};
    this.filtersApplied = 0;
    this.format = format;
  }
  
  static createParameters(funderName: string = null, title: string = null, chartType: string = null): any {
    return {
      index_name: funderName,
      title: title,
      type: chartType
    };
  }

}

export type FilterType = "fundingL0"|"start_year" | "end_year" | "co-funded" | "foslvl1" | "foslvl2" | "publicly-funded";

export class IndicatorFilterUtils {
  public static filteredFields = {
    "year":{
      "result": "result.year",
      "indi_pub_downloads_year": "indi_pub_downloads_year.year",   //exclude indi_pub_downloads_year.year because it throws errors. when there is a solution remove the exclusion
      "indi_pub_downloads":"indi_pub_downloads.result.year",
      "result_apc":"result_apc.result.year",
      "result_apc_affiliations":"result_apc_affiliations.result.year",
      "result_country":"result_country.result.year",
      "indi_impact_measures": "indi_impact_measures.result.year",
      "project": "project.start year"
    },
    "fundingL0":{
      "result": "result.project funding level 0",
      "project": "project.funding level 0",
      "country":"country.organization.project.funding level 0",
      "organization":"organization.project.funding level 0"
    },
    "co-funded":{
      "result": "result.No of funders",
    },
    "foslvl1":
      {
      "publication":"publication.topics.result.result_fos.lvl1",
      "result":"result.topics.result.result_fos.lvl1",
      "indi_pub_downloads":"indi_pub_downloads.result.result_fos.lvl1",
      "indi_pub_downloads_year":"indi_pub_downloads_year.result.result_fos.lvl1",
       "indi_impact_measures":"indi_impact_measures.result.result_fos.lvl1",
        "result_apc":"result_apc.result.result_fos.lvl1",
        "result_apc_affiliations":"result_apc_affiliations.result.result_fos.lvl1",
        "result_country":"result_country.result.result_fos.lvl1",
        "historical_snapshots_irish_fos":"historical_snapshots_irish_fos.lvl1"
      },
    "foslvl2":{
      "publication":"publication.topics.result.result_fos.lvl2",
      "result":"result.topics.result.result_fos.lvl2",
      "indi_pub_downloads":"indi_pub_downloads.result.result_fos.lvl2",
      "indi_pub_downloads_year":"indi_pub_downloads_year.result.result_fos.lvl2",
      "indi_impact_measures":"indi_impact_measures.result.result_fos.lvl2",
      "result_apc":"result_apc.result.result_fos.lvl2",
      "result_apc_affiliations":"result_apc_affiliations.result.result_fos.lvl2",
      "result_country":"result_country.result.result_fos.lvl2",
      "historical_snapshots_irish_fos":"historical_snapshots_irish_fos.lvl2"
      },
    "publicly-funded":{
      "result":"result.indi_pub_publicly_funded.publicly_funded",
      "indi_pub_downloads":"indi_pub_downloads.result.indi_pub_publicly_funded.publicly_funded",
      "indi_pub_downloads_year":"indi_pub_downloads_year.result.indi_pub_publicly_funded.publicly_funded",
      "indi_impact_measures":"indi_impact_measures.result.indi_pub_publicly_funded.publicly_funded",
      "result_apc":"result_apc.result.indi_pub_publicly_funded.publicly_funded",
      "result_apc_affiliations":"result_apc_affiliations.result.indi_pub_publicly_funded.publicly_funded",
      "result_country":"result_country.result.indi_pub_publicly_funded.publicly_funded"
    }

  }
 static getFieldForTable(field, table){
    if(["publication", "software", "dataset", "other", "result"].indexOf(table)!=-1 && IndicatorFilterUtils.filteredFields[field]["result"]){
      return IndicatorFilterUtils.filteredFields[field]["result"];
    }else{
      return IndicatorFilterUtils.filteredFields[field][table];
    }
 }
  static getFilter(fieldPath: string, filterType:FilterType, value:string|string[] =null) {
    let tablename = fieldPath.split(".")[0];
    if ((filterType == "start_year" || filterType == "end_year") && (IndicatorFilterUtils.getFieldForTable("year",tablename))){
      if (filterType == "start_year") {
        return '{"groupFilters":[{"field":"' + IndicatorFilterUtils.getFieldForTable("year",tablename) + '","type":">=","values":["' + ChartHelper.prefix + 'start_year' + ChartHelper.suffix + '"]}],"op":"AND"}';
      } else if (filterType == "end_year") {
        return '{"groupFilters":[{"field":"' + IndicatorFilterUtils.getFieldForTable("year",tablename) + '","type":"<=","values":["' + ChartHelper.prefix + 'end_year' + ChartHelper.suffix + '"]}],"op":"AND"}';
      }
    }
    if (filterType == "fundingL0" && IndicatorFilterUtils.getFieldForTable("fundingL0",tablename)) {
      return '{"groupFilters":[{"field":"' + IndicatorFilterUtils.getFieldForTable("fundingL0",tablename) + '","type":"=","values":["' + ChartHelper.prefix + 'fundingL0' + ChartHelper.suffix + '"]}],"op":"AND"}';

    }else if (filterType == "co-funded" && IndicatorFilterUtils.getFieldForTable("co-funded",tablename)) {
      return '{"groupFilters":[{"field":"' + IndicatorFilterUtils.getFieldForTable("co-funded",tablename) + '","type":">","values":["1"]}],"op":"AND"}';
    }else if (filterType == "publicly-funded" && IndicatorFilterUtils.getFieldForTable("publicly-funded",tablename)) {
      return '{"groupFilters":[{"field":"' + IndicatorFilterUtils.getFieldForTable("publicly-funded",tablename) + '","type":"=","values":["' + (value=="true"?"1":"0") +'"]}],"op":"AND"}';
    }else if (filterType == "foslvl1" && IndicatorFilterUtils.getFieldForTable("foslvl1",tablename) && value && value.length > 0) {
      let filterString = '{"groupFilters":[' ;
      let filters = [];
      for(let v of value) {
        filters.push('{"field":"' + IndicatorFilterUtils.getFieldForTable("foslvl1",tablename) + '","type":"=","values":["' + v + '"]}');
      }
      filterString+=filters.join(", ")
      filterString+='],"op":"OR"}'
      return filterString;
    }else if (filterType == "foslvl2" && IndicatorFilterUtils.getFieldForTable("foslvl2",tablename) && value && value.length > 0) {
      let filterString = '{"groupFilters":[' ;
      let filters = [];
      for(let v of value) {
        filters.push('{"field":"' + IndicatorFilterUtils.getFieldForTable("foslvl2",tablename) + '","type":"=","values":["' + v + '"]}');
      }
      filterString+=filters.join(", ")
      filterString+='],"op":"OR"}'
      return filterString;
    }
    return "";
  }

  static filterIndexOf(filterToAdd, currentFilters):any{
    for(let fi =0; fi< currentFilters.length; fi++){
      for(let gfi =0; gfi< currentFilters[fi]["groupFilters"].length; gfi++ ){
        if(currentFilters[fi]["groupFilters"][gfi].field == filterToAdd['groupFilters'][0]['field'] && currentFilters[fi]["groupFilters"][gfi].type == filterToAdd['groupFilters'][0]['type']){
            return {"filter":fi, "groupFilter":gfi};
        }
      }
    }
    return null;
  }
}

/**
 * @deprecated
 *
 * TODO: Remove after merge with develop
 * */
export enum StakeholderEntities {
	STAKEHOLDER = 'Dashboard',
	FUNDER = 'Funder',
	RI = 'Research Initiative',
	ORGANIZATION = 'Research Institution',
	PROJECT = 'Project',
  COUNTRY = 'National',

	STAKEHOLDERS = 'Dashboards',
	FUNDERS = 'Funders',
	RIS = 'Research Initiatives',
	ORGANIZATIONS = 'Research Institutions',
	PROJECTS = 'Projects'
}
