/**
 *                                                                            
 * Copyright (c) 2011, 2016 - 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:   
 * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation 
 * 
 * 
 *  This copyright notice shows up in the generated Java code
 * 
 */

package org.eclipse.osbp.xtext.cubedsl.scoping

import java.util.ArrayList
import org.eclipse.emf.ecore.EObject
import org.eclipse.emf.ecore.EReference
import org.eclipse.emf.ecore.InternalEObject
import org.eclipse.osbp.dsl.semantic.common.types.LDataType
import org.eclipse.osbp.dsl.semantic.entity.LEntity
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute
import org.eclipse.osbp.dsl.semantic.entity.LEntityFeature
import org.eclipse.osbp.dsl.semantic.entity.LEntityReference
import org.eclipse.osbp.xtext.cubedsl.CubeAggregatorEnum
import org.eclipse.osbp.xtext.cubedsl.CubeDSLPackage
import org.eclipse.osbp.xtext.cubedsl.CubeDimension
import org.eclipse.osbp.xtext.cubedsl.CubeDimensionEntity
import org.eclipse.osbp.xtext.cubedsl.CubeDimensionEntityEntity
import org.eclipse.osbp.xtext.cubedsl.CubeDimensionUsage
import org.eclipse.osbp.xtext.cubedsl.CubeEntity
import org.eclipse.osbp.xtext.cubedsl.CubeHierarchy
import org.eclipse.osbp.xtext.cubedsl.CubeMeasure
import org.eclipse.osbp.xtext.cubedsl.CubePackage
import org.eclipse.osbp.xtext.cubedsl.CubeTypeEntity
import org.eclipse.xtext.common.types.impl.JvmParameterizedTypeReferenceImpl
import org.eclipse.xtext.scoping.IScope
import org.eclipse.xtext.scoping.Scopes

/**
 * This class contains custom scoping description.
 * 
 * see : http://www.eclipse.org/Xtext/documentation.html#scoping
 * on how and when to use it 
 * 
 */
//class CubeDSLScopeProvider extends AbstractDeclarativeScopeProvider {
class CubeDSLScopeProvider extends AbstractCubeDSLScopeProvider /*XbaseWithAnnotationsScopeProvider*/ {

	@Override
	override IScope getScope(EObject context, EReference reference) {
		if (reference == CubeDSLPackage.Literals.CUBE_DIMENSION_ENTITY_ENTITY__OVER_VALUE) {
			return getScope_CubeDimensionEntityEntityOverValue(context as CubeDimensionEntityEntity)
		} else if (reference == CubeDSLPackage.Literals.CUBE_DIMENSION_USAGE__OVER_VALUE) {
			return getScope_CubeDimensionUsage_OverValue(context as CubeDimensionUsage)
		} else if (reference == CubeDSLPackage.Literals.CUBE_MEASURE__MEASURE_COL) {
			return getScope_CubeMeasureCol(context as CubeMeasure)
		} else if ((reference == CubeDSLPackage.Literals.CUBE_LEVEL__LEVEL_COL_VALUE) ||
			(reference == CubeDSLPackage.Literals.CUBE_LEVEL__LEVEL_NAME_COL_VALUE) ||
			(reference == CubeDSLPackage.Literals.CUBE_LEVEL__LEVEL_CAPTION_COL_VALUE) ||
			(reference == CubeDSLPackage.Literals.CUBE_LEVEL__LEVEL_ORDINAL_COL_VALUE) ||
			(reference == CubeDSLPackage.Literals.CUBE_LEVEL_PROP__LEVEL_PROP_COL_VALUE)) {
			return getScope_CubeEntityColRef(context as EObject)
		} else if (reference == CubeDSLPackage.Literals.CUBE_ENTITY__KEY_VALUE) {
			return getScope_CubeEntity_KeyValue(context as CubeEntity)
		} else if (reference == CubeDSLPackage.Literals.CUBE_DIMENSION_USAGE__SOURCE_VALUE) {
			return getScope_CubeDimensionUsage_SourceValue(context as CubeDimensionUsage)
		} else {
			return super.getScope(context, reference)
		}

	}

	def IScope getScope_CubeDimensionUsage_SourceValue(CubeDimensionUsage cubeDimUsage) {
		var result = <EObject>newArrayList
		var eObj = cubeDimUsage.eContainer
		while (!(eObj instanceof CubePackage)) {
			eObj = eObj.eContainer
		}
		var cubePackage = (eObj as CubePackage)
		if (cubePackage !== null) {
			for (CubeDimension cubeDim : cubePackage.dimensions) {
				if (cubeDim.name !== null) {
					result.add(cubeDim)
				}
			}
		}
		return Scopes.scopeFor(result)
	}

	def getScope_CubeDimensionUsage_OverValue(CubeDimensionUsage cubeDimUsage) {
		var result = <EObject>newArrayList
		var dimEntities = <String>newArrayList
		var dimUsageSource = cubeDimUsage.getSourceValue
		var LEntity cubeEnt = cubeDimUsage.getCubeEntity
		if (dimUsageSource !== null) {
			for (CubeHierarchy cubeHierarchy : dimUsageSource.hierarchies) {
				dimEntities.add(cubeHierarchy.dimEntityName)
			}
			if (dimUsageSource.typeTime) {
				for (LEntityAttribute entityAttr : cubeEnt.allAttributes) {
					if (entityAttr.date) {
						result.add(entityAttr)
					}
				}
			}
		}
		if (cubeEnt !== null) {
			// If the cube entity is as the used entity for the dimension
			// only its attributes are used as foreign key 
			if (dimEntities.contains(cubeEnt.name)) {
				for (LEntityAttribute entityAttr : cubeEnt.allAttributes) {
					result.add(entityAttr)
				}
			} else {
				for (LEntityReference entityRef : cubeEnt.allReferences) {
					if (dimEntities.contains(entityRef.getTypeName)) {
						result.add(entityRef)
					}
				}
			}
		}
		return Scopes.scopeFor(result)
	}

	def ArrayList<EObject> getRefResultList(LEntity cubeEnt, ArrayList<EObject> result) {
		for (LEntityReference entityRef : cubeEnt.allReferences) {
			if (entityRef.name !== null) {
				result.add(entityRef)
			}
		}
		return result
	}

	def getCubeEntity(EObject childEObj) {
		var LEntity cubeEnt = null;
		var eObj = childEObj.eContainer
		while (!(eObj instanceof CubeTypeEntity)) {
			if (eObj !== null) {
				eObj = eObj.eContainer
			}
		}
		if (eObj !== null) {
			cubeEnt = (eObj as CubeTypeEntity).entityRef.entityValue
		}
		return cubeEnt
	}

	def getScope_CubeMeasureCol(CubeMeasure cubeMeasure) {
		var result = <EObject>newArrayList
		var LEntity cubeEnt = cubeMeasure.getCubeEntity
		if (cubeEnt !== null) {
			// if measure uses count aggregator only numeric entity attributes are provided
			if (cubeMeasure.aggregator !== null && (cubeMeasure.aggregator.equals(CubeAggregatorEnum.COUNT) ||
				cubeMeasure.aggregator.equals(CubeAggregatorEnum.DSC))) {
				result = cubeEnt.getRefResultList(result)
			} else {
				for (LEntityAttribute entityAttr : cubeEnt.allAttributes) {
					if (entityAttr.type !== null && entityAttr.entity.isNormalAttribute(entityAttr) &&
						(entityAttr.type instanceof LDataType) && (entityAttr.type as LDataType).isNumeric) {
						result.add(entityAttr)
					}
				}
			}
		}
		return Scopes.scopeFor(result)
	}

	def boolean isNumeric(LDataType type) {
		val JvmParameterizedTypeReferenceImpl typeRef = type.jvmTypeReference as JvmParameterizedTypeReferenceImpl
		if (typeRef !== null) {
			var typeIdentifier = ""
			if (typeRef.basicGetType().eIsProxy && (typeRef.basicGetType() instanceof InternalEObject)) {
				typeIdentifier = (typeRef.basicGetType() as InternalEObject).eProxyURI.fragment
			} else {
				typeIdentifier = typeRef.identifier
			}
			switch (typeIdentifier) {
				case Short.typeName,
				case Integer.typeName,
				case Long.typeName,
				case Double.typeName,
				case Float.typeName: {
					return true
				}
				default: {
					return false
				}
			}
		}
		return false
	}

	def IScope getScope_CubeEntityColRef(EObject context) {
		var result = <EObject>newArrayList
		var eObj = context
		while (!((eObj instanceof CubeDimensionEntity) || (eObj instanceof CubeDimensionEntityEntity) ||
			(eObj instanceof CubeTypeEntity))) {
			if (eObj !== null) {
				eObj = eObj.eContainer
			}
		}
		if (eObj !== null) {
			var LEntity cubeEnt = null;
			if (eObj instanceof CubeDimensionEntityEntity) {
				cubeEnt = (eObj as CubeDimensionEntityEntity).entityRef.entityValue
			} else if (eObj instanceof CubeDimensionEntity) {
				cubeEnt = (eObj as CubeDimensionEntity).entityRef.entityValue
			} else if (eObj instanceof CubeTypeEntity) {
				cubeEnt = (eObj as CubeTypeEntity).entityRef.entityValue
			}
			result = cubeEnt.getAttrResultList(result)
		}
		return Scopes.scopeFor(result)
	}

	def IScope getScope_CubeDimensionEntityEntityOverValue(CubeDimensionEntityEntity cubeDimEntityEntity) {
		var result = <EObject>newArrayList
		var eObj = cubeDimEntityEntity.eContainer
		while (!(eObj instanceof CubeDimensionEntity)) {
			if (eObj !== null) {
				eObj = eObj.eContainer
			}
		}
		if (eObj !== null) {
			if (eObj instanceof CubeDimensionEntity) {
				result = cubeDimEntityEntity.getJoinableRefsResultList((eObj as CubeDimensionEntity), result)
			}
		}
		return Scopes.scopeFor(result)
	}

	def IScope getScope_CubeEntity_KeyValue(CubeEntity entity) {
		var result = <EObject>newArrayList
		if (entity !== null) {
			result = entity.entityValue.getAttrResultList(result)
		}
		return Scopes.scopeFor(result)
	}

	def getJoinableRefsResultList(CubeDimensionEntityEntity cubeDimEntityEntity, CubeDimensionEntity entity,
		ArrayList<EObject> result) {
		if (entity !== null && entity.entityRef !== null && entity.entityRef.entityValue !== null &&
			entity.entityRef.entityValue.name !== null) {
			var LEntity cubeEnt = entity.entityRef.entityValue
			for (LEntityReference lEntRef : cubeEnt.allReferences) {
				if (cubeDimEntityEntity.entityRef !== null && cubeDimEntityEntity.entityRef.entityValue !== null &&
					cubeDimEntityEntity.entityRef.entityValue.name !== null &&
					cubeDimEntityEntity.entityRef.entityValue.name.equals(lEntRef.type.name)) {
					result.add(lEntRef)
				}
			}
		}
		return result;
	}

	def getAttrResultList(LEntity cubeEnt, ArrayList<EObject> result) {
		if (cubeEnt !== null) {
			for (LEntityAttribute entityAttr : cubeEnt.allAttributes) {
				if (entityAttr.name !== null) {
					result.add(entityAttr)
				}
			}
		}
		return result;
	}

	def getAllFeaturesResultList(LEntity cubeEnt, ArrayList<EObject> result) {
		if (cubeEnt !== null) {
			for (LEntityFeature entityFeature : cubeEnt.allFeatures) {
				if (entityFeature.name !== null) {
					result.add(entityFeature)
				}
			}
		}
		return result;
	}

	def getDimEntityName(CubeHierarchy cubeHierarchy) {
		if (cubeHierarchy !== null && cubeHierarchy.cubeDimEntity !== null &&
			cubeHierarchy.cubeDimEntity.entityRef !== null &&
			cubeHierarchy.cubeDimEntity.entityRef.entityValue !== null) {
				return cubeHierarchy.cubeDimEntity.entityRef.entityValue.name
			}
		}

		def getTypeName(LEntityReference entityRef) {
			if (entityRef.type.name !== null && entityRef.type.name !== null) {
				return entityRef.type.name
			}
		}

		def isDate(LEntityAttribute entityAttr) {
			return (entityAttr.type instanceof LDataType && (entityAttr.type as LDataType).date)
		}
	}
	