import CollectionConfig from './CollectionConfig';

class NISVCatalogueConfig extends CollectionConfig {
	constructor(clientId, user, collectionId, stats, info) {
		super(clientId, user, collectionId, stats, info);
	}

	getNamespace() {
		return 'http://av.beeldengeluid.nl/';
	}

	//the type varies for B&G
	getCollectionMediaTypes() {
		return [];
	}

	//used to prevent graphs to blow up in case the minimum date is really low (because of incorrect data)
	getMinimunYear() {
		return 1850;
	}

	//override the nisv-catalogue-aggr__layer_asr
	getCollectionIndices() {
	 	return [this.getCollectionId()]
	}

	//this means the resource viewer needs to request access to the content before it can show them
	requiresPlayoutAccess() {
		return true;
	}

	getPreferredDateField() {
		return 'bg:publications.bg:publication.bg:sortdate';
	}

	getFacets() {
		return [
			{
				field: 'bg:publications.bg:publication.bg:broadcasters.bg:broadcaster',
				title : 'Broadcaster',
				id : 'broadcaster',
				type : 'string'
			},
			{
				field: 'bga:series.bg:genres.bg:genre.keyword',
				title : 'Genre (series)',
				id : 'genre',
				type : 'string'
			},
			{
				field: 'bg:keywords.bg:keyword.keyword',
				title : 'Keyword',
				id : 'keyword',
				type : 'string'
			}
		];
	}

	getMetadataFieldCategories() {
		return [
			{
				id : 'titles',
				label : 'Titles',
				fields : [
					'bga:series.bg:maintitles.bg:title',
					'bga:season.bg:maintitles.bg:title',
					'bga:segment.bg:maintitles.bg:title',
					'bg:maintitles.bg:title'
				]
			},
			{
				id : 'descriptions',
				label : 'Descriptions',
				fields : [
					'bg:summary',
					'bg:description',
					'bga:segment.bg:description',
					'bg:museum-description',
					'bga:series.bg:museum-description',
					'bga:segment.bg:museum-description'
				]
			},
			{
				id : 'subtitles',
				label : 'Subtitles',
				fields : [
					'bg:transcripts.bg:transcript.bg:text',
					'bga:segment.bg:transcripts.bg:transcript.bg:text'
				]
			},
			{
				id : 'asr',
				label : 'Spraaktranscripten',
				nestedPath : 'layer__asr',
				fields : [
					'layer__asr.words'
				]
			}
		]
	}

	getItemDetailData(result, currentDateField) {
		result = this.formatSearchResult(result);
		const formattedResult = {}
		formattedResult.resourceId = result._id;
		formattedResult.index = result._index;
		formattedResult.docType = result._type;
		formattedResult.title = this.__extractTitle(result);
		formattedResult.description = this.__extractDescription(result);
		const dateInfo = this.__extractDateInfo(result, currentDateField);
		if(dateInfo) {
			formattedResult.date = dateInfo.date;
			formattedResult.dateField = dateInfo.field;
		}
		formattedResult.externalSourceInfo = this.__getExternalSourceInfo(result);
		formattedResult.specialProperties = this.__extractSpecialProperties(result);

		const content = this.__extractPlayableContent(result);
		formattedResult.playableContent = content.playableContent;
		formattedResult.mediaTypes = content.mediaTypes;
		formattedResult.rawData = result;

		/*
		//THIS IS ONLY WHEN USING THE MULTI-LAYERED APPROACH OF HAVING MULTIPLE INDEXES
		//if the user did not specify a search string there will be no inner hits and thus no fragment metadata!

		//the media fragment is passed to the resource viewer, so it will skip to that piece of media
		//TODO this should be changed, since the media fragment is now reflected as a URL, which should be hidden to
		//prevent easily downloading it
		if(result._type == 'media_fragment' &&
			formattedResult.playableContent &&
			formattedResult.playableContent.length > 0) {
			formattedResult.mediaFragment = {
				url : formattedResult.playableContent[0].url,
				assetId : formattedResult.playableContent[0].assetId,
				start : result.start || 0,
				end : result.start + result.duration || 5000,
				snippet : result.words ? '(...) "' + result.words  + '" (...)' : '',
				layer : 'asr'
			}

		}*/

		return formattedResult;
	}

	/*toPrettyFieldName(esFieldName) {
		if(esFieldName) {
			//first split the field based on a dot
			const tmp = esFieldName.split('.');

			let isKeywordField = false;

			//if the last field is called raw or keyword (ES reserved names), drop it
			if(tmp[tmp.length -1] == 'raw' || tmp[tmp.length -1] == 'keyword') {
				isKeywordField = true;
				tmp.pop();
			}

			let leaf = tmp[tmp.length-1];
			let parent = null;
			let metadataLayer = '';
			let prettyName = '';

			//first determine the 'metadata layer', e.g. season, series, program or segment
			if (tmp[0].indexOf('bga:') == -1) {
		 		metadataLayer = 'program';
		 	} else {
		 		metadataLayer = tmp[0].substring(tmp[0].indexOf(':') + 1);
		 		tmp.splice(0,1);
		 	}

		 	if(tmp.length > 0) {
				parent = tmp[0].substring(tmp[0].indexOf(':') + 1);
	 		}

	 		prettyName = metadataLayer + ' => ' + leaf
	 		if(parent) {
	 			prettyName += ' (in: ' + parent + ')'
	 		}
	 		if(isKeywordField) {
	 			prettyName += ' *';
	 		}
			return prettyName.replace('bg:', '');
		}
		return esFieldName;
	}*/

	toPrettyFieldName(esFieldName) {
		if(esFieldName) {
			//first split the field based on a dot
			let tmp = esFieldName.split('.');

			// remove namespaces
			tmp = tmp.map((field)=>(field.substring(field.indexOf(":") + 1)));

			let isKeywordField = false;

			//if the last field is called raw or keyword (ES reserved names), drop it
			if(tmp[tmp.length -1] == 'raw' || tmp[tmp.length -1] == 'keyword') {
				isKeywordField = true;
				tmp.pop();
			}

			let leaf = tmp.pop();

			// move @ to end of fieldname
			if (leaf.substring(0,1) == '@'){
				leaf = leaf.substring(1) + '@';
			}
			let origin = tmp.join(".");
			if (origin){
				origin = ' => ' + origin;
			}
			return leaf + origin + (isKeywordField ? ' *' : '');
		}
		return esFieldName;
	}

	__extractTitle(result) {
		let title = null;
		//first check the series title
		if (result.hasOwnProperty('bga:series')) {
			const series = result['bga:series'];
			if (series.hasOwnProperty('bg:maintitles') && series['bg:maintitles'].hasOwnProperty('bg:title')) {
				title = series['bg:maintitles']['bg:title'].join(' / ');
			}
		}
		//then check the season title
		if (result.hasOwnProperty('bga:season')) {
			const season = result['bga:season'];
			if (season.hasOwnProperty('bg:maintitles') && season['bg:maintitles'].hasOwnProperty('bg:title')) {
				title = title ? title + '; ' : '';
				title += season['bg:maintitles']['bg:title'].join(' / ');
			}
		}
		//then check the expression title
		if (result.hasOwnProperty('bg:maintitles') && result['bg:maintitles'].hasOwnProperty('bg:title')) {
			title = title ? title + ': ' : '';
			title += result['bg:maintitles']['bg:title'].join(' / ');
			if (result.hasOwnProperty('bg:subtitles') && result['bg:subtitles'].hasOwnProperty('bg:title')) {
				title += ' - ' + result['bg:subtitles']['bg:title'].join('; ');
			}
		}
		return title;
	}

	__extractDescription(result) {
		if (result.hasOwnProperty('bg:summary')) {
			return result['bg:summary'];
		} else {
			const temp = [result.broadcaster, result.genre]
			return temp.filter((d) => {return d ? true : false}).join(' ');
		}
		return null;
	}

	__extractDateInfo(result, currentDateField) {
		let usePublicationDate = true;
		if(currentDateField) {
			//console.debug(currentDateField);
			//if the selected date field is something else than the default sortdate try to fetch something different
			if(currentDateField.indexOf('sortdate') == -1) {

			}

		}
		if(usePublicationDate) {
			if (result.hasOwnProperty('bg:publications') && result['bg:publications'].hasOwnProperty('bg:publication')) {
				let pubs = result['bg:publications']['bg:publication'];
				if(pubs.hasOwnProperty('bg:sortdate')) {
					return {
						date : pubs['bg:sortdate'],
						field : 'bg:publications.bg:publication.bg:sortdate'
					}
				} else if(pubs.map) { //make sure it is actually an array
					return {
						date : pubs.map((pub) => {
							return pub.hasOwnProperty('bg:sortdate') ? pub['bg:sortdate'] : '';
						}).join(' / '),
						field : 'bg:publications.bg:publication.bg:sortdate'
					}
				}
			}
		}
		return null;
	}

	__extractPlayableContent(result) {
		let mimeType = 'video/mp4';

		//determine whether the content is radio or not
		if(result.hasOwnProperty('bga:series')) {
			const series = result['bga:series'];
			if(series.hasOwnProperty('bg:distributionchannel') &&
				result['bga:series']['bg:distributionchannel'].toLowerCase() == 'radio') {
				mimeType = 'audio/mp3';
			} else if (series.hasOwnProperty('bg:catalog') && series['bg:catalog'] == 'Foto') {
				mimeType = 'image/jpeg';
			}
		}

		//fill the playable content array
		let playableContent = [];
		if(result['bg:carriers'] && result['bg:carriers']['bg:carrier']) {
			playableContent = playableContent.concat(
				this.__extractPlayableContentFromCarriers(
					result['bg:carriers']['bg:carrier'],
					mimeType
				)
			)
		}

		//add the content attached to the segments
		if(result['bga:segment']) {
			result['bga:segment'].forEach((segment) => {
				if(segment['bg:carriers'] && segment['bg:carriers']['bg:carrier']) {
					playableContent = playableContent.concat(
						this.__extractPlayableContentFromCarriers(
							segment['bg:carriers']['bg:carrier'],
							mimeType
						)
					)
				}
			});
		}

		//now make sure the mediaTypes are all there
		let mediaTypes = null;
		if(playableContent && playableContent.length > 0) {
			//set the media types for the search snippet media type icon
			//mediaTypes = ['image'];
			mediaTypes = mimeType == 'audio/mp3' ? ['audio'] : ['video'];
		} else {
			playableContent = null;
		}

		return {
			playableContent : playableContent,
			mediaTypes : mediaTypes
		}
	}

	__extractPlayableContentFromCarriers(carrierElement, mimeType) {
		if(carrierElement) {
			let carriers = carrierElement.hasOwnProperty('bg:carrierreference') ? [carrierElement] : carrierElement;
			return carriers.filter(c => c['bg:carriertype'] == 'media archive')
				.sort((a,b) => parseInt(a['bg:sequencenumber'] > b['bg:sequencenumber']))
				.map(c => {
					//console.debug(c)
					//console.debug(c['bg:startoncarrier'] + ' ' + c['bg:endoncarrier'])
					return {
						url : _play +
							'/api/play/' +
							this.__getContentServerId(mimeType) +
							'/' +
							this.__getContentId(c['bg:carrierreference']) +
							'?cid=' +
							_clientId +
							'&at=' +
							_chickenStock,
						mimeType : mimeType,
						assetId : c['bg:carrierreference'],
						contentId : this.__getContentId(c['bg:carrierreference']),
						contentServerId : this.__getContentServerId(mimeType)
					}
				})
		}
		return [];
	}

	__getContentServerId(mimeType) {
		let contentServerId = 'beng-video'
		if (mimeType.indexOf('audio') != -1) {
			contentServerId = 'beng-audio'
		}
		return contentServerId
	}

	__getContentId(guci) {
		let i = guci.length-1;
		let cid = '';
		while(i >= 0) {
			cid += String.fromCharCode(guci.charCodeAt(i) + 1);
			i--;
		}
		return cid;
	}

	__getExternalSourceInfo(result) {
		if(result.hasOwnProperty('dc:relation')) {
			return {
				url :result['dc:relation'],
				message : null
			}
		}
		return null;
	}

	//these are the properties that will be shown in the regular item details table
	__extractSpecialProperties(result) {
		const specialProperties = {};
		//broadcaster
		if (result.hasOwnProperty('bg:publications') && result['bg:publications'].hasOwnProperty('bg:publication')) {
			if (result['bg:publications']['bg:publication'].hasOwnProperty('bg:broadcasters')) {
				specialProperties['Broadcaster'] = result['bg:publications']['bg:publication']['bg:broadcasters']['bg:broadcaster'];
			}
		}
		//genre
		if (result.hasOwnProperty('bg:genres') && result['bg:genres'].hasOwnProperty('bg:genre')) {
			specialProperties['Genre'] = result['bg:genres']['bg:genre'];
		}
		return specialProperties;
	}

}

export default NISVCatalogueConfig;