import {Injectable} from '@angular/core';
import {Citation, Dataset, Identifier, License, Organization, Person} from '../model/jsonld-document';
import * as _ from 'lodash';
import {properties} from '../../../../../environments/environment';
import {ParsingFunctions} from "../../../landingPages/landing-utils/parsingFunctions.class";

@Injectable()
export class OpenAireJsonldConverterService {

	constructor() {

	}

	createHome(name, URL, logoURL, description:string, searchActionRoute ): any {
		const organization = {};
		organization["@context"] = "http://schema.org";
		organization["@id"] = URL+"/#organization";
		organization["@type"] = "Organization";
		organization["name"] = name;
		organization["url"] = URL;
		if(logoURL && logoURL.length > 0 ) {
			organization["logo"] = logoURL;
		}
		if(description){
			organization["description"] = description;
		}
		if((properties.domain.indexOf("connect.openaire.eu")!=-1 || properties.domain.indexOf("explore.openaire.eu")!=-1|| properties.domain.indexOf("monitor.openaire.eu")!=-1) && properties.baseLink == "/") {
			const sameAs = ["https://www.openaire.eu",
				"https://www.facebook.com/groups/openaire/",
				"https://www.twitter.com/OpenAIRE_eu",
				"https://www.linkedin.com/groups/OpenAIRE-3893548",
				"https://www.slideshare.net/OpenAIRE_eu",
				"https://www.youtube.com/channel/UChFYqizc-S6asNjQSoWuwjw"];
			organization["sameAs"] = sameAs;
		}
		if(searchActionRoute) {
			return [organization, this.createDefaultSearchPage(name, URL,logoURL,description,searchActionRoute)];
		}
		return organization;
	}
	createDefaultSearchPage(name, URL, logoURL, description:string, searchRoute ){
		const searchPage = {};
		searchPage["@context"] = "http://schema.org";
		searchPage["@id"] = URL + "/#search";
		searchPage["@type"] = "Website";
		searchPage["name"] = name;
		searchPage["url"] = URL + searchRoute;
	/* no valid property for Website
		if(logoURL && logoURL.length > 0 ) {
			searchPage["logo"] = logoURL;
		}*/
		if (description) {
			searchPage["description"] = description;
		}
		const action = {};
		action["@type"] = "SearchAction";
		action["@id"] = URL + "/#search-action";
		action["target"] = URL+ searchRoute +  "?fv0={search_term_string}&f0=q";
		action["query-input"] = "required name=search_term_string";

		searchPage["potentialAction"] = action;
		return  searchPage;
	}
	createSimplePage(name, URL, description:string = null): any {
		const buffer = {};
		buffer["@context"] = "http://schema.org";
		buffer["@type"] = "WebPage";
		buffer["name"] = name;
		buffer["url"] = URL;
		if(description){
			buffer["description"] = description;
		}else{
			buffer["description"] = name;
		}
		buffer["@id"] = URL;
		return buffer;
	}
	createSearchPage(name, URL, logoURL, searchAction:boolean = true, description:string = null, searchActionRoute = null): any {
		const buffer = {};
		buffer["@context"] = "http://schema.org";
		buffer["@type"] = "SearchResultsPage";
		buffer["name"] = name;
		if(description){
			buffer["description"] = description;
		}
		buffer["url"] = URL;
		buffer["@id"] = URL;
		buffer["logo"] = logoURL;
		buffer["isPartOf"] = properties.domain+ properties.baseLink +"/#search";
		if(searchAction){
			 return [buffer,this.createDefaultSearchPage(name, URL,logoURL,description,searchActionRoute) ]
		}
		return buffer;
	}
	convertResult(result: any, URL, searchActionRoute = null): Dataset {
		const doc = new Dataset();

		doc.title = this.getTitle(result);
		doc.headline = doc.title;
		if(this.getSubTitle(result)){
			doc.alternativeHeadline = this.getSubTitle(result);
		}
		doc.issn = this.getISSN(result);
		doc.description = this.getDescription(result);
		doc.identifier = this.getIdentifier(result);
		doc.id = URL;
		doc.url = URL;
		doc.sameAs = this.getSameAs(result);
		doc.creator = this.getCreator(result);
		doc.dateCreated = this.getDateCreated(result);
		doc.citation = this.getCitation(result);
		doc.license = this.getLicense(result);
		doc.keyword = this.getKeyword(result);
		doc.isPartOf = [];
    if(properties.adminToolsPortalType !== 'eosc') {
      let fosSubjects = this.getKeyword(result, "FOS");
      let sdgSubjects = this.getKeyword(result, "SDG");
      for (let fos of fosSubjects ? fosSubjects : []) {
        doc.isPartOf.push(URL.split('/search/')[0] + searchActionRoute + "?fos=" + encodeURIComponent('"' + fos + '"'));
      }
      for (let sdg of sdgSubjects ? sdgSubjects : []) {
        doc.isPartOf.push(URL.split('/search/')[0] + searchActionRoute + "?sdg=" + encodeURIComponent('"' + sdg + '"'));
      }
    }
		return doc;
	}

	convertProject(project: any, URL): Organization {
		const doc = new Organization();
		doc.title = (project.title)?project.title:project.acronym;
		doc.identifier = new Array<Identifier>();
		doc.identifier.push({id:project.funding.code, schema: "grantid"});
		let funder = new Organization();
		funder.id = properties.domain + properties.baseLink+"#funder-"+project.funding.funderShortName;
		funder.title = project.funding.funderName;
		doc.funder = funder;
		doc.url = URL;
    doc.id = URL;

    doc["description"] = [];
    if(project.description) {
      let parsing = new ParsingFunctions();
      let abstracts = parsing.parseDescription(project.description, true);
      doc["description"] = [abstracts ?(abstracts.substring(0,4997)+(abstracts.substring(0,4997).length == 4997?'...':'')):"" ];
    } else {
      doc["description"].push(("project" + (project.title ? "," + project.title : "") + (project.funding && project.funding.funderName ? ", funder: " + project.funding.funderName : "") + (project.acronym ? "," + project.acronym : "")));
    }

    doc.sameAs =[project.url];
		return doc;
}

convertOrganization(organization: any, URL, description:string = null): Organization {
	const doc = new Organization();

	doc.title =  organization.title.name ;
	doc.legalName = organization.name;
	doc.areaServed = organization.country;
	doc.url = URL;
	doc.id = URL;
	doc["description"] = [];
	doc["description"].push(((organization.title.name?organization.title.name:"") + " - " + (organization.name?organization.name:"")));
	return doc;
}

convertDatasource(datasource: any, URL, otherUrl): Organization {
	const doc = new Organization();

	doc.title = datasource.title.name?datasource.title.name:datasource.officialName;
	//doc.identifier = datasource.contractNum;
	doc.legalName = datasource.officialName;
	if(datasource.countries && datasource.countries.length > 0){
		doc.areaServed = datasource.countries[0];
	}
	doc.url = URL;
	doc.id = URL;

  doc["description"] = [];
  if(datasource.description) {
    let parsing = new ParsingFunctions();
    let abstracts = parsing.parseDescription(datasource.description, true);
    doc["description"] = [abstracts ?(abstracts.substring(0,4997)+(abstracts.substring(0,4997).length == 4997?'...':'')):"" ];
  } else {
    doc["description"].push(datasource.title.name?datasource.title.name:datasource.officialName);
  }

	if(datasource.oaiPmhURL || otherUrl || datasource.title.url){
		doc.sameAs = [];
		if(otherUrl){
			doc.sameAs = otherUrl;
		}
		if(datasource.oaiPmhURL){
			doc.sameAs.push(datasource.oaiPmhURL);

		}
		if(datasource.title.url){
			doc.sameAs.push(datasource.title.url);
		}
	}
	return doc;
}

	private getTitle(result: any): String[] {
		const title = _.get(result, "result.metadata.oaf:entity.oaf:result.title", null);
		let return_title;
		if(title && Array.isArray(title) ){
      for(let i=0; i<title.length; i++) {
        if(title[i] && title[i].content) {
          if(!return_title || title[i].classid == "main title") {
            return_title = String(title[i].content);
          }
          if(title[i].classid == "main title") {
            break;
          }
        }
      }
      if(!return_title) {
        return_title = "";
      }
      return return_title;
			// return (title[0] && title[0].content)?title[0].content:"";
		}else{
			return (title && title.content)?title.content:"";
		}

	}
	private getSubTitle(result: any): String[] {
		const title = _.get(result, "result.metadata.oaf:entity.oaf:result.title", null);
		if(title && Array.isArray(title) ){
			if(title[1] && title[1].classid == "subtitle") {
				return title[1].content;
			}
		}
		return null;
	}
	private getISSN(result: any): String[] {
		const item = _.get(result, "result.metadata.oaf:entity.oaf:result.journal.issn", null);
		if (!item) return null;
		return [item as String];
	}
	private getDescription(result: any): String[] {
		const item = _.get(result, "result.metadata.oaf:entity.oaf:result.description", null);
		if (!item) return [ "" + this.getTitle(result)];
		let parsing = new ParsingFunctions();
		let abstracts = parsing.parseDescription(item, true);
		return [abstracts ?(abstracts.substring(0,4997)+(abstracts.substring(0,4997).length == 4997?'...':'')):"" ];
	}

	private getDateCreated(result: any): String[] {
		const item = _.get(result, "result.metadata.oaf:entity.oaf:result.dateofacceptance", null);
		if (!item) return null;
		return [item as String];
	}

	private getLicense(result: any): License[] {
		const item = _.get(result, "result.metadata.oaf:entity.oaf:result.bestaccessright", null);
		if (!item) return null;
		if (!_.has(item, "classid")) return null;
		if (!_.has(item, "classname")) return null;
		if (!_.has(item, "schemeid")) return null;

		return [{
			title: [_.get(item, "classname")],
			identifier: [{
				id: _.get(item, "classid"),
				schema: _.get(item, "schemeid")
			}]
		}];
	}

	private getIdentifier(result: any): Identifier[] {
		const item = _.get(result, "result.metadata.oaf:entity.oaf:result.pid", null);
		if (!item) return null;
		const array = new Array<Identifier>();
		if (Array.isArray(item)) {
			const itemArray = item as Array<any>;
			for (var i = 0; i < itemArray.length; i += 1) {
				const val = this.getSingleIdentifier(itemArray[i]);
				if (val) array.push(val);
			}
		}
		else {
			const val = this.getSingleIdentifier(item);
			if (val) array.push(val);
		}
		if (array.length == 0) return null;
		return array;
	}

	private getSingleIdentifier(item: any): Identifier {
		if (!_.has(item, "classname")) return null;
		if (!_.has(item, "content")) return null;
		return {
			schema: _.get(item, "classname"),
			id: _.get(item, "content")
		};
	}

	private getSameAs(result: any): String[] {
		const instances = _.get(result, "result.metadata.oaf:entity.oaf:result.children.instance", null);
		if (!instances) return null;
		if (!Array.isArray(instances)) return null;

		const array = new Array<String>();

		const instanceArray = instances as Array<any>;
		for (var i = 0; i < instanceArray.length; i += 1) {
			const webresources = _.get(instanceArray[i], "webresource", null);
			if (!webresources) continue;
			if (Array.isArray(webresources)) {
				const webresourceArray = webresources as Array<any>;
				for (var q = 0; q < webresourceArray.length; q += 1) {
					const url = _.get(webresourceArray[q], "url", null);
					if (!url) continue;
					array.push(url as String);
				}
			}
			else {
				const url = _.get(webresources, "url", null);
				if (!url) continue;
				array.push(url as String);
			}
		}
		if (array.length == 0) return null;
		return array;
	}

	private getKeyword(result: any, classification:'FOS'|'SDG' |null = null): String[] {
		const subjects = _.get(result, "result.metadata.oaf:entity.oaf:result.subject", null);
		if (!subjects) return null;
		if (!Array.isArray(subjects)) return null;

		const array = new Array<String>();

		const subjectArray = subjects as Array<any>;
		for (var i = 0; i < subjectArray.length; i += 1) {
			const classid = _.get(subjectArray[i], "classid", null);
			if(classification && classid !==classification) continue;

			const sub = _.get(subjectArray[i], "content", null);
			if (!sub) return null;

			array.push(sub as String);
		}
		if (array.length == 0) return null;
		return array.slice(0,10);
	}

	private getCreator(result: any): Person[] {
		const item = _.get(result, "result.metadata.oaf:entity.oaf:result.creator", null);
		if (!item) return null;
		const array = new Array<Person>();
		if (Array.isArray(item)) {
			const itemArray = item as Array<any>;
			for (var i = 0; i < itemArray.length; i += 1) {
				const val = this.getSinglePerson(itemArray[i]);
				if (val) array.push(val);
			}
		}
		else {
			const val = this.getSinglePerson(item);
			if (val) array.push(val);
		}
		if (array.length == 0) return null;
		return array;
	}

	private getSinglePerson(item: any): Person {
		if (!_.has(item, "surname") && !_.has(item, "name") && !_.has(item, "content")) return null;
		return {
			familyName: _.get(item, "surname", null),
			givenName: _.get(item, "name", null),
			name: _.get(item, "content", null)
		};
	}

	private getCitation(result: any): Citation[] {
		const item = _.get(result, "result.metadata.oaf:entity.extraInfo.citations.citation", null);
		if (!item) return null;
		const array = new Array<Citation>();
		if (Array.isArray(item)) {
			const itemArray = item as Array<any>;
			for (var i = 0; i < itemArray.length; i += 1) {
				const val = this.getSingleCitation(itemArray[i]);
				if (val) array.push(val);
			}
		}
		else {
			const val = this.getSingleCitation(item);
			if (val) array.push(val);
		}
		if (array.length == 0) return null;
		return array;
	}

	private getSingleCitation(item: any): Citation {
		if (!_.has(item, "rawText")) return null;
		if (!_.has(item, "id")) return null;

		const array = new Array<Identifier>();

		const ids = _.get(item, "id", null);
		if (Array.isArray(ids)) {
			const idsArray = ids as Array<any>;

			for (var i = 0; i < idsArray.length; i += 1) {
				const type = _.get(idsArray[i], "type", null);
				const value = _.get(idsArray[i], "value", null);
				if (!type || !value) continue;
				array.push({
					id: value,
					schema: type
				});
			}
		}
		else {
			const type = _.get(ids, "type", null);
			const value = _.get(ids, "value", null);
			if (type && value) {
				array.push({
					id: value,
					schema: type
				});
			}
		}

		if (array.length == 0) return null;

		return {
			title: [_.get(item, "rawText")],
			identifier: array
		};
	}


}
