/**
 * Copyright (c) 2011, 2015 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0 
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *         Florian Pirchner - Initial implementation
 */
package org.eclipse.osbp.dsl.dto.xtext.jvmmodel

import com.google.inject.Inject
import java.util.List
import org.eclipse.osbp.dsl.dto.xtext.extensions.AnnotationExtension
import org.eclipse.osbp.dsl.dto.xtext.extensions.DtoModelExtensions
import org.eclipse.osbp.dsl.semantic.common.types.LAttributeMatchingConstraint
import org.eclipse.osbp.dsl.semantic.common.types.LKeyAndValue
import org.eclipse.osbp.dsl.semantic.common.types.LResultFilters
import org.eclipse.osbp.dsl.semantic.dto.LDto
import org.eclipse.osbp.dsl.semantic.dto.LDtoAbstractAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedAttribute
import org.eclipse.osbp.dsl.semantic.dto.LDtoInheritedReference
import org.eclipse.osbp.dsl.semantic.dto.LDtoReference
import org.eclipse.osbp.dsl.semantic.entity.LBean
import org.eclipse.osbp.dsl.semantic.entity.LBeanAttribute
import org.eclipse.osbp.dsl.semantic.entity.LBeanReference
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute
import org.eclipse.osbp.dsl.semantic.entity.LEntityReference
import org.eclipse.osbp.runtime.common.annotations.AsGrid
import org.eclipse.osbp.runtime.common.annotations.AsKanbanOrdering
import org.eclipse.osbp.runtime.common.annotations.AsKanbanState
import org.eclipse.osbp.runtime.common.annotations.AsTable
import org.eclipse.osbp.runtime.common.annotations.CreateAt
import org.eclipse.osbp.runtime.common.annotations.CreateBy
import org.eclipse.osbp.runtime.common.annotations.Dirty
import org.eclipse.osbp.runtime.common.annotations.Dispose
import org.eclipse.osbp.runtime.common.annotations.DomainDescription
import org.eclipse.osbp.runtime.common.annotations.DomainKey
import org.eclipse.osbp.runtime.common.annotations.DomainReference
import org.eclipse.osbp.runtime.common.annotations.Filter
import org.eclipse.osbp.runtime.common.annotations.FilterDepth
import org.eclipse.osbp.runtime.common.annotations.Id
import org.eclipse.osbp.runtime.common.annotations.OnKanbanCard
import org.eclipse.osbp.runtime.common.annotations.Range
import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraint
import org.eclipse.osbp.runtime.common.annotations.TargetEnumConstraints
import org.eclipse.osbp.runtime.common.annotations.UIGroup
import org.eclipse.osbp.runtime.common.annotations.UniqueEntry
import org.eclipse.osbp.runtime.common.annotations.UpdateAt
import org.eclipse.osbp.runtime.common.annotations.UpdateBy
import org.eclipse.osbp.runtime.common.annotations.Version
import org.eclipse.xtext.common.types.JvmAnnotationReference
import org.eclipse.xtext.common.types.JvmField
import org.eclipse.xtext.common.types.JvmGenericType
import org.eclipse.xtext.common.types.JvmOperation
import org.eclipse.xtext.common.types.JvmType
import org.eclipse.xtext.common.types.JvmTypeReference
import org.eclipse.xtext.common.types.util.TypeReferences
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder

/** 
 * This class is responsible to generate the Annotations defined in the entity model
 */
class AnnotationCompiler extends org.eclipse.osbp.dsl.common.xtext.jvmmodel.AnnotationCompiler {

	@Inject extension JvmTypesBuilder
	@Inject extension TypeHelper
	@Inject extension DtoModelExtensions
	@Inject extension AnnotationExtension
	@Inject
	private TypeReferences references;

	def protected dispatch void internalProcessAnnotation(LDto dto, JvmGenericType jvmType) {
		dto.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmType);
	}

	def protected dispatch void internalProcessAnnotation(LDtoReference prop, JvmGenericType jvmType) {
		prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(jvmType);
	}

	def protected dispatch void internalProcessAnnotation(LDtoReference prop, JvmField field) {
		prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(field);

		field.annotations += prop.toAnnotation(typeof(DomainReference))
		if (prop.cascading) {
			prop.toValidAnnotation(field)
		}

		// create the properties annotations
		prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)
	}

	def protected List<LKeyAndValue> mergeKeyAndValues(LDtoInheritedAttribute att) {
		val keyAndValues = newArrayList()

		// add all datatype properties to the list
		att.inheritedFeature.addDatatypeKeyAndValues(keyAndValues)

		// add the attribute properties
		keyAndValues.addAll(att.inheritedFeature.properties)

		// add the attribute properties
		keyAndValues.addAll(att.properties)

		// remove duplicate keys
		keyAndValues.removeDuplicateKeys

		return keyAndValues
	}

	def protected List<LKeyAndValue> mergeKeyAndValues(LDtoInheritedReference ref) {
		val keyAndValues = newArrayList()

		// add the attribute properties
		keyAndValues.addAll(ref.inheritedFeature.properties)

		// add the attribute properties
		keyAndValues.addAll(ref.properties)

		// remove duplicate keys
		keyAndValues.removeDuplicateKeys

		return keyAndValues
	}

	def protected dispatch void internalProcessAnnotation(LDtoAttribute prop, JvmField field) {
		prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(field);

		if (prop.id || prop.uuid) {
			field.annotations += prop.toAnnotation(typeof(Id))
		}

		if (prop.version) {
			field.annotations += prop.toAnnotation(typeof(Version))
		}

		if (prop.domainKey) {
			field.annotations += prop.toAnnotation(typeof(DomainKey))
		}

		if (prop.domainDescription) {
			field.annotations += prop.toAnnotation(typeof(DomainDescription))
		}

		if (prop.dirty) {
			field.annotations += prop.toAnnotation(typeof(Dirty))
		}

		// create the properties annotations
		prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)

		if (prop.type.validAllowed) {
			prop.toValidAnnotation(field)
		}
		super.toDatatypeBasedConstraintAnnotations(prop, field)
	}

	def protected dispatch void internalProcessAnnotation(LDtoInheritedAttribute prop, JvmField field) {
		prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(field);

		if (prop.inheritedFeature.id || prop.inheritedFeature.uuid) {
			field.annotations += prop.toAnnotation(typeof(Id))
		}

		if (prop.inheritedFeature.version) {
			field.annotations += prop.toAnnotation(typeof(Version))
		}

		if (prop.inheritedFeature.domainKey) {
			field.annotations += prop.toAnnotation(typeof(DomainKey))
		}

		if (prop.inheritedFeature.domainDescription) {
			field.annotations += prop.toAnnotation(typeof(DomainDescription))
		}

		// create the properties annotations
		prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)

		if (prop.inheritedFeature.type.validAllowed) {
			prop.toValidAnnotation(field)
		}

		// add the range and filter annotation
		if (prop.inheritedFeature.isFiltering) {
			field.annotations += prop.toAnnotation(typeof(Filter))
		}
		if (prop.inheritedFeature.isRangeFiltering) {
			field.annotations += prop.toAnnotation(typeof(Range))
		}

		if (prop.inheritedFeature.isUniqueEntry) {
			field.annotations += prop.toAnnotation(typeof(UniqueEntry))
		}

		if (prop.inheritedFeature instanceof LEntityAttribute) {
			val att = prop.inheritedFeature as LEntityAttribute

			if (att.isOnKanbanCard) {
				field.annotations += prop.toAnnotation(typeof(OnKanbanCard))
			}

			if (att.isAsKanbanOrdering) {
				field.annotations += prop.toAnnotation(typeof(AsKanbanOrdering))
			}

			if (att.asKanbanState) {
				field.annotations += prop.toAnnotation(typeof(AsKanbanState))
			}
			
			if(att.annotationPresent(references.findDeclaredType(typeof(UpdateBy), att))) {
				field.annotations += prop.toAnnotation(typeof(UpdateBy))
			}
			
			if(att.annotationPresent(references.findDeclaredType(typeof(UpdateAt), att))) {
				field.annotations += prop.toAnnotation(typeof(UpdateAt))
			}
			
			if(att.annotationPresent(references.findDeclaredType(typeof(CreateBy), att))) {
				field.annotations += prop.toAnnotation(typeof(CreateBy))
			}
			
			if(att.annotationPresent(references.findDeclaredType(typeof(CreateAt), att))) {
				field.annotations += prop.toAnnotation(typeof(CreateAt))
			}

			if (att.isGrouped) {
				val groupAnnotation = prop.toAnnotation(typeof(UIGroup))
				groupAnnotation.addAnnAttr(prop, "name", att.groupName)
				field.annotations += groupAnnotation
			}
		}

		// also inherit annotations from the entities
		prop.inheritedFeature.toInheritedConstraintAnnotations(field)
	}
	
	def boolean annotationPresent(LEntityAttribute attribute, JvmType type) {
		for(anno : attribute.resolvedAnnotations) {
			if(anno.annotation.annotationType === type){
				return true
			}
		}
		return false
	}

	def protected dispatch void internalProcessAnnotation(LDtoInheritedReference prop, JvmField field) {
		prop.resolvedAnnotations.filter([!exclude]).map([annotation]).translateAnnotationsTo(field);

		field.annotations += prop.toAnnotation(typeof(DomainReference))

		val inheritedRef = prop.inheritedFeature
		if (inheritedRef instanceof LEntityReference) {
			if (inheritedRef.resultFilters != null) {
				inheritedRef.resultFilters.addConstraintsAnno(field, prop.type)
			}

			if (inheritedRef.cascading) {
				prop.toValidAnnotation(field)
			}

			// also inherit annotations from the entities
			inheritedRef.toInheritedConstraintAnnotations(field)

			// create the properties annotations
			prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)

			if (inheritedRef.filterDepth >= 0) {
				val anno = inheritedRef.toAnnotation(typeof(FilterDepth))
				anno.addAnnAttr(inheritedRef, "depth", inheritedRef.filterDepth)
				field.annotations += anno
			}

		} else if (inheritedRef instanceof LBeanReference) {
			if (inheritedRef.resultFilters != null) {
				inheritedRef.resultFilters.addConstraintsAnno(field, prop.type)
			}

			if (inheritedRef.cascading) {
				prop.toValidAnnotation(field)
			}

			// also inherit annotations from the entities
			inheritedRef.toInheritedConstraintAnnotations(field)

			// create the properties annotations
			prop.toPropertiesAnnotation(mergeKeyAndValues(prop), field)
		}

		if (inheritedRef.isGrouped) {
			val groupAnnotation = prop.toAnnotation(typeof(UIGroup))
			groupAnnotation.addAnnAttr(prop, "name", inheritedRef.groupName)
			field.annotations += groupAnnotation
		}
		if (inheritedRef.asGrid) {
			field.annotations += prop.toAnnotation(typeof(AsGrid))
		}
		if (inheritedRef.asTable) {
			field.annotations += prop.toAnnotation(typeof(AsTable))
		}
		
	}

	def void addConstraintsAnno(LResultFilters constraints, JvmField jvmField, LDto mapsTo) {

		// process the LAttributeMatchingConstraint
		if (!constraints.resultFilters.filter[it instanceof LAttributeMatchingConstraint].empty) {

			// collect all inner annotations
			val innerAnnotations = newArrayList()
			constraints.resultFilters.filter[it instanceof LAttributeMatchingConstraint].map [
				it as LAttributeMatchingConstraint
			].forEach [
				val enumClassTypeRef = attribute.name.findReplacementEnum(mapsTo)
				if (enumClassTypeRef != null) {
					val innerAnno = constraints.toAnnotation(typeof(TargetEnumConstraint))
					innerAnno.addAnnAttr(it, "targetProperty", attribute.name)
					innerAnno.addAnnAttr(it, "enumClass", enumClassTypeRef)
					innerAnno.addAnnAttr(it, "enumLiteral", matchingLiteral.name)
					innerAnnotations += innerAnno
				}
			]

			// now create the outer annotation and add the array of inner annotations
			val mainAnno = constraints.toAnnotation(typeof(TargetEnumConstraints))
			mainAnno.addAnnAttr(constraints, "constraints",
				innerAnnotations.toArray(<JvmAnnotationReference>newArrayOfSize(innerAnnotations.length)))
			jvmField.annotations += mainAnno
		}
	}

	/** 
	 * Iterates all attributes of the target dto. If a matching att name was found, the jvmType proxy will be returned.
	 */
	def JvmTypeReference findReplacementEnum(String property, LDto mapsTo) {
		for (att : mapsTo.allFeatures.filter[it instanceof LDtoAbstractAttribute].map[it as LDtoAbstractAttribute]) {
			if (att instanceof LDtoInheritedAttribute) {
				if (att.inheritedFeature?.name.equals(property)) {
					return att.toDtoTypeReference
				}
			} else {
				if (att.name.equals(property)) {
					return att.toDtoTypeReference
				}
			}
		}
		return null
	}

	def dispatch addDisposeFieldAnnotation(LDto dto, JvmField field) {
		addAnno(dto, field, dto.toAnnotation(typeof(Dispose)))
	}

	def dispatch addDisposeFieldAnnotation(LDto dto, JvmOperation op) {
		addAnno(dto, op, dto.toAnnotation(typeof(Dispose)))
	}

	def dispatch boolean isValidAllowed(LBean type) {
		return true;
	}

	def dispatch void toInheritedConstraintAnnotations(LDtoInheritedAttribute prop, JvmField jvmField) {
		val feature = prop.inheritedFeature
		if (feature instanceof LBeanAttribute) {
			feature.toInheritedConstraintAnnotations(jvmField)
		} else if (feature instanceof LEntityAttribute) {
			feature.toInheritedConstraintAnnotations(jvmField)
		}
	}

	def dispatch void toInheritedConstraintAnnotations(LBeanAttribute prop, JvmField jvmField) {

		for (c : prop.constraints) {
			c.toConstraintAnnotation(jvmField)
		}

		if (prop.constraints.empty) {
			super.toDatatypeBasedConstraintAnnotations(prop, jvmField)
		}
	}

	def dispatch void toInheritedConstraintAnnotations(LBeanReference prop, JvmField jvmField) {

		for (c : prop.constraints) {
			c.toConstraintAnnotation(jvmField)
		}
	}

	def dispatch void toInheritedConstraintAnnotations(LEntityAttribute prop, JvmField jvmField) {

		for (c : prop.constraints) {
			c.toConstraintAnnotation(jvmField)
		}

		if (prop.constraints.empty) {
			super.toDatatypeBasedConstraintAnnotations(prop, jvmField)
		}
	}

	def dispatch void toInheritedConstraintAnnotations(LEntityReference prop, JvmField jvmField) {

		for (c : prop.constraints) {
			c.toConstraintAnnotation(jvmField)
		}
	}
}
