import DocumentAPI from '../../../api/DocumentAPI';
import CollectionUtil from '../../../util/CollectionUtil';
import IDUtil from '../../../util/IDUtil';

const AnnotationUtil = {

	/*************************************************************************************
	 --------------------------- W3C BUSINESS LOGIC HERE ---------------------------------
	*************************************************************************************/

	//called from components that want to create a new annotation with a proper target
	generateW3CEmptyAnnotation : function(user, project, collectionId, resourceId, mediaObject = null, segmentParams = null) {
		//Resource or MediaObject annotations ALL start with this as part of the target
		let resourceTarget = AnnotationUtil.generateResourceLevelTarget(collectionId, resourceId);
		let refinedTarget = null;
		//ALL THESE ARE MANDATORY TO BE ABLE TO PROPERLY ANNOTATE A MEDIA OBJECT!
		//TODO DELETE/UPDATE NON-COMPATIBLE ANNOTATIONS
		if(mediaObject && mediaObject.mimeType && mediaObject.assetId) {
			let refinedBy = null; //when selecting a piece of the target
			let mediaType = null;
			if(mediaObject.mimeType.indexOf('video') != -1) {
				mediaType = 'Video';
				refinedBy = AnnotationUtil.__generateSegmentSelector(segmentParams, 'temporal')
			} else if(mediaObject.mimeType.indexOf('audio') != -1) {
				mediaType = 'Audio';
				refinedBy = AnnotationUtil.__generateSegmentSelector(segmentParams, 'temporal')
			} else if(mediaObject.mimeType.indexOf('image') != -1) {
				mediaType = 'Image';
				refinedBy = AnnotationUtil.__generateSegmentSelector(segmentParams, 'spatial')
			}
			refinedTarget = AnnotationUtil.__generateMediaObjectTarget(
				resourceTarget,
				refinedBy,
				mediaType,
				mediaObject.assetId
			)
		}

		return {
			id : null, //should be generated on the server?
			user : user.id,
			project : project ? project.id : null, //no suitable field found in W3C so far
			body : null,
			target : refinedTarget ? refinedTarget : resourceTarget
		}
	},

	//currently only used for bookmarking lots of resources
	generateEmptyW3CMultiTargetAnnotation : function(user, project, collectionId, resourceIds, motivation='bookmarking') {
		const annotation = {
			id : null,
			user : user.id,
			project : project ? project.id : null, //no suitable field found in W3C so far
			motivation : motivation,
			target : resourceIds.map((rid) => AnnotationUtil.generateResourceLevelTarget(collectionId, rid)),
			body : null
		}
		return annotation
	},

	generateBookmarkGroupAnnotation : function(user, project, collectionId, groupLabel) {
		const annotation = AnnotationUtil.generateEmptyW3CMultiTargetAnnotation(user, project, collectionId, []); //empty target
		annotation.id = IDUtil.guid(); //Note: normally generated on the server, but used as guid in this component
		annotation.body = [{
			"annotationType": "classification",
			"vocabulary": "clariahwp5-bookmark-group",
			"label": groupLabel,
			"user": user.id
		}];
		return annotation;
	},

	toUpdatedAnnotation(user, project, collectionId, resourceId, mediaObject, segmentParams, annotation) {
		if(!annotation) {
			annotation = AnnotationUtil.generateW3CEmptyAnnotation(
				user,
				project,
				collectionId,
				resourceId,
				mediaObject,
				segmentParams
			);
		} else if(segmentParams && annotation.target.selector.refinedBy) {
			annotation.target.selector.refinedBy = segmentParams.rect ?
				this.__generateSegmentSelector(segmentParams, 'spatial') :
				this.__generateSegmentSelector(segmentParams, 'temporal')
		}
		return annotation;
	},

	removeSourceUrlParams(url) {
		if(url.indexOf('?') != -1 && url.indexOf('cgi?') == -1) {
			return url.substring(0, url.indexOf('?'));
		}
		return url
	},

	generateResourceLevelTarget(collectionId, resourceId) {
		return {
			type : 'Resource',
			source : resourceId,
			selector : {
				type: 'NestedPIDSelector',
				value: [
					{
						id: collectionId,
						type: ['Collection'],
						property: 'isPartOf'
					},
					{
						id: resourceId,
						type: ['Resource'],
						property: 'isPartOf'
					}
				]
			}
		}
	},

	__generateSegmentSelector : function(params, segmentType) {
		if(!params) {
			return null
		}

		if(segmentType == 'temporal') {
			if(params.start && params.end &&
				params.start != -1 && params.end != -1) {
				return {
					type: "FragmentSelector",
					conformsTo: "http://www.w3.org/TR/media-frags/",
					value: '#t=' + params.start + ',' + params.end,
					start: params.start,
					end: params.end
    			}
			}
		} else if(segmentType == 'spatial') {
			if(params.rect && typeof(params.rect) == 'object') {
				return {
					type: "FragmentSelector",
					conformsTo: "http://www.w3.org/TR/media-frags/",
					value: '#xywh=' + params.rect.x + ',' + params.rect.y + ',' + params.rect.w + ',' + params.rect.h,
					rect : params.rect
    			}
			}
		}
		return null
	},

	//TODO make this suitable for resource annotations too (now it's currently only for mediaobject annotations)
	__generateMediaObjectTarget : function(basicTarget, refinedBy, mediaType, assetId) {
		let targetType = 'MediaObject';
		if (refinedBy) {
			basicTarget.selector.refinedBy = refinedBy
			targetType = 'Segment'
		}

		const representationTypes = ['Representation', 'MediaObject', mediaType]
		if (refinedBy) {
			representationTypes.push('Segment')
		}
		basicTarget.selector.value.push({
			id: assetId,
			type: representationTypes,
			property: 'isRepresentation'
		})

		basicTarget.type = targetType;
		basicTarget.source = assetId;
		return basicTarget
	},

	/*************************************************************************************
	 ******************************* USED BY PLAYERS TO GET THE RIGHT SEGMENTS ***********
	*************************************************************************************/

	//get the index of the segment within a list of annotations of a certain target
	getSegmentIndex(annotations, annotation) {
		if(annotations && annotation) {
			let i = 0;
			for(const a of annotations) {
				if(a.target.selector.refinedBy) {
					if(a.id == annotation.id) {
						return i;
					}
					i++;
				}
			}
		}
		return -1;
	},

	//get the nth segment within a list of annotations of a certain target
	getSegment(annotations, index) {
		if(annotations) {
			index = index < 0 ? 0 : index;
			let i = 0;
			for(const a of annotations) {
				if(a.target.selector.refinedBy) {
					if(i == index) {
						return a;
					}
					i++;
				}
			}
		}
		return null;
	},

	/*************************************************************************************
	 ************************************* ANNOTATION BODY PRETTIFY **********************
	*************************************************************************************/

	annotationBodyToPrettyText(body) {
		if(body.annotationType === 'comment') {
			return body.text ? body.text.substring(0, 200) : '';
		} else if(body.annotationType === 'classification') {
			return body.label;
		} else if(body.annotationType === 'metadata') {
			if(body.properties && body.properties.length > 0) {
				let text = body.properties[0].key;
				text += ': ' + (body.properties[0].value ? body.properties[0].value.substring(0,200) : '');
				text += ' (+ ' + (body.properties.length -1) + ' other properties)';
				return text
			}
		}
		return '-';
	},


	/*************************************************************************************
	 ************************************* W3C MEDIA FRAGMENTS HELPERS ***************
	*************************************************************************************/

	extractAnnotationTargetDetails : function(annotation) {
		//check if there is a temporal fragment in the annotation target
		let frag = AnnotationUtil.extractTemporalFragmentFromAnnotation(annotation.target);
		if(frag) {
			return { type : 'temporal', frag : frag, source : annotation.target.source }
		} else { //then see if there is a spatial fragment
			frag = AnnotationUtil.extractSpatialFragmentFromAnnotation(annotation);
			if(frag) {
				return { type : 'spatial', frag : frag, source : annotation.target.source}
			}
		}
		return {type : 'object', frag : null, source : annotation.target.source}
	},

	extractTemporalFragmentFromAnnotation : function(target) {
		if(target && target.selector && target.selector.refinedBy && target.selector.refinedBy.start) {
			return {
				start : target.selector.refinedBy.start,
				end : target.selector.refinedBy.end
			}
		}
		return null;
	},

	extractSpatialFragmentFromAnnotation : function(annotation) {
		if(annotation && annotation.target && annotation.target.selector && annotation.target.selector.refinedBy) {
			return {
				x: annotation.target.selector.refinedBy.x,
				y: annotation.target.selector.refinedBy.y,
				w: annotation.target.selector.refinedBy.w,
				h: annotation.target.selector.refinedBy.h
			}
		}
		return null;
	},


	/*************************************************************************************
	 *********************EXTRACT STUFF FROM CONTAINED ANNOTATION CARDS ******************
	*************************************************************************************/

	extractAnnotationCardTitle : function(annotation) {
		if(annotation && annotation.body) {
			const cards = annotation.body.filter((a) => {
				return a.annotationType === 'metadata'
			});
			if(cards.length > 0) {
				const title = cards[0].properties.filter((p) => {
					return p.key == 'title' || p.key == 'titel';
				});
				return title.length > 0 ? title[0].value : null;
			}
		}
		return null;
	},

	/*************************************************************************************
	 ************************************* URL VALIDATION ****************************
	*************************************************************************************/

	isValidURL(url) {
		const urlPattern =/^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i;
		return urlPattern.test(url);
	}

}

export default AnnotationUtil;