/**
 * 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 v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 * 
 *  Contributors:
 * 	   Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
 * 
 * 
 *  This copyright notice shows up in the generated Java code
 */
package org.eclipse.osbp.xtext.chart.scoping;

import com.google.common.base.Objects;
import java.util.ArrayList;
import javax.inject.Inject;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.osbp.dsl.semantic.entity.LEntityAttribute;
import org.eclipse.osbp.xtext.chart.ChartDSLPackage;
import org.eclipse.osbp.xtext.chart.ChartDatamart;
import org.eclipse.osbp.xtext.datamartdsl.AxisEnum;
import org.eclipse.osbp.xtext.datamartdsl.DatamartAxis;
import org.eclipse.osbp.xtext.datamartdsl.DatamartCube;
import org.eclipse.osbp.xtext.datamartdsl.DatamartCubeElement;
import org.eclipse.osbp.xtext.datamartdsl.DatamartDefinition;
import org.eclipse.osbp.xtext.datamartdsl.DatamartEntity;
import org.eclipse.osbp.xtext.datamartdsl.DatamartMember;
import org.eclipse.osbp.xtext.datamartdsl.DatamartNavigation;
import org.eclipse.osbp.xtext.datamartdsl.DatamartOwner;
import org.eclipse.osbp.xtext.datamartdsl.DatamartProperty;
import org.eclipse.osbp.xtext.datamartdsl.DatamartSource;
import org.eclipse.osbp.xtext.datamartdsl.DatamartTask;
import org.eclipse.osbp.xtext.datamartdsl.jvmmodel.DatamartDSLJvmModelInferrer;
import org.eclipse.xtext.resource.EObjectDescription;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.MapBasedScope;
import org.eclipse.xtext.xbase.annotations.typesystem.XbaseWithAnnotationsBatchScopeProvider;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Extension;

@SuppressWarnings("all")
public class ChartScopeProvider extends XbaseWithAnnotationsBatchScopeProvider {
  @Inject
  @Extension
  private DatamartDSLJvmModelInferrer datamartInferrer;
  
  @Override
  public IScope getScope(final EObject context, final EReference reference) {
    boolean _equals = Objects.equal(reference, ChartDSLPackage.Literals.CHART_AXIS__AXIS);
    if (_equals) {
      return this.getScope_Chart_Axis_axis(context);
    }
    return super.getScope(context, reference);
  }
  
  public IScope getScope_Chart_Axis_axis(final EObject object) {
    ArrayList<IEObjectDescription> result = CollectionLiterals.<IEObjectDescription>newArrayList();
    EObject eObj = object;
    while ((!(eObj instanceof ChartDatamart))) {
      EObject _eContainer = eObj.eContainer();
      eObj = _eContainer;
    }
    boolean _notEquals = (!Objects.equal(eObj, null));
    if (_notEquals) {
      DatamartDefinition datamart = ((ChartDatamart) eObj).getDatamartRef();
      boolean _and = false;
      boolean _notEquals_1 = (!Objects.equal(datamart, null));
      if (!_notEquals_1) {
        _and = false;
      } else {
        DatamartSource _source = datamart.getSource();
        boolean _notEquals_2 = (!Objects.equal(_source, null));
        _and = _notEquals_2;
      }
      if (_and) {
        DatamartSource _source_1 = datamart.getSource();
        if ((_source_1 instanceof DatamartCube)) {
          DatamartSource _source_2 = datamart.getSource();
          EList<DatamartCubeElement> _axisslicer = ((DatamartCube) _source_2).getAxisslicer();
          for (final DatamartCubeElement axis : _axisslicer) {
            if ((axis instanceof DatamartAxis)) {
              AxisEnum _name = ((DatamartAxis) axis).getName();
              String literal = _name.getLiteral();
              IEObjectDescription _create = EObjectDescription.create(literal, ((DatamartAxis) axis));
              result.add(_create);
            }
          }
        } else {
          DatamartSource _source_3 = datamart.getSource();
          if ((_source_3 instanceof DatamartEntity)) {
            DatamartSource _source_4 = datamart.getSource();
            this.getEntityAxes(((DatamartEntity) _source_4), result);
          } else {
            DatamartSource _source_5 = datamart.getSource();
            if ((_source_5 instanceof DatamartTask)) {
              String _literal = AxisEnum.COLUMNS.getLiteral();
              DatamartSource _source_6 = datamart.getSource();
              IEObjectDescription _create_1 = EObjectDescription.create(_literal, ((DatamartTask) _source_6));
              result.add(_create_1);
              String _literal_1 = AxisEnum.ROWS.getLiteral();
              DatamartSource _source_7 = datamart.getSource();
              IEObjectDescription _create_2 = EObjectDescription.create(_literal_1, ((DatamartTask) _source_7));
              result.add(_create_2);
            }
          }
        }
      }
    }
    return MapBasedScope.createScope(IScope.NULLSCOPE, result);
  }
  
  public void getEntityAxes(final DatamartEntity entity, final ArrayList<IEObjectDescription> result) {
    EList<DatamartNavigation> _navigations = entity.getNavigations();
    for (final DatamartNavigation navigation : _navigations) {
      {
        if ((navigation instanceof DatamartMember)) {
          DatamartEntity _datamartEntity = ((DatamartMember) navigation).getDatamartEntity();
          this.getEntityAxes(_datamartEntity, result);
          DatamartEntity _datamartEntity_1 = ((DatamartMember) navigation).getDatamartEntity();
          EList<DatamartProperty> _properties = _datamartEntity_1.getProperties();
          for (final DatamartProperty property : _properties) {
            AxisEnum _axis = property.getAxis();
            String _literal = _axis.getLiteral();
            IEObjectDescription _create = EObjectDescription.create(_literal, property);
            result.add(_create);
          }
        }
        if ((navigation instanceof DatamartOwner)) {
          DatamartEntity _datamartEntity_2 = ((DatamartOwner) navigation).getDatamartEntity();
          this.getEntityAxes(_datamartEntity_2, result);
          DatamartEntity _datamartEntity_3 = ((DatamartOwner) navigation).getDatamartEntity();
          EList<DatamartProperty> _properties_1 = _datamartEntity_3.getProperties();
          for (final DatamartProperty property_1 : _properties_1) {
            AxisEnum _axis_1 = property_1.getAxis();
            String _literal_1 = _axis_1.getLiteral();
            IEObjectDescription _create_1 = EObjectDescription.create(_literal_1, property_1);
            result.add(_create_1);
          }
        }
      }
    }
    EList<DatamartProperty> _properties = entity.getProperties();
    for (final DatamartProperty property : _properties) {
      AxisEnum _axis = property.getAxis();
      boolean _notEquals = (!Objects.equal(_axis, null));
      if (_notEquals) {
        AxisEnum _axis_1 = property.getAxis();
        String _literal = _axis_1.getLiteral();
        IEObjectDescription _create = EObjectDescription.create(_literal, property);
        result.add(_create);
      } else {
        AxisEnum _axis_2 = property.getAxis();
        String _literal_1 = _axis_2.getLiteral();
        IEObjectDescription _create_1 = EObjectDescription.create(_literal_1, property);
        result.add(_create_1);
      }
    }
  }
  
  public void getEntityProperties(final DatamartEntity entity, final ArrayList<IEObjectDescription> result, final String requestedAxisName) {
    EList<DatamartNavigation> _navigations = entity.getNavigations();
    for (final DatamartNavigation navigation : _navigations) {
      {
        if ((navigation instanceof DatamartMember)) {
          DatamartEntity _datamartEntity = ((DatamartMember) navigation).getDatamartEntity();
          this.getEntityProperties(_datamartEntity, result, requestedAxisName);
          DatamartEntity _datamartEntity_1 = ((DatamartMember) navigation).getDatamartEntity();
          EList<DatamartProperty> _properties = _datamartEntity_1.getProperties();
          for (final DatamartProperty property : _properties) {
            AxisEnum _axis = property.getAxis();
            String _literal = _axis.getLiteral();
            boolean _equals = _literal.equals(requestedAxisName);
            if (_equals) {
              String _propertyName = this.datamartInferrer.getPropertyName(property, null);
              LEntityAttribute _propertyRef = property.getPropertyRef();
              IEObjectDescription _create = EObjectDescription.create(_propertyName, _propertyRef);
              result.add(_create);
            }
          }
        }
        if ((navigation instanceof DatamartOwner)) {
          DatamartEntity _datamartEntity_2 = ((DatamartOwner) navigation).getDatamartEntity();
          this.getEntityProperties(_datamartEntity_2, result, requestedAxisName);
          DatamartEntity _datamartEntity_3 = ((DatamartOwner) navigation).getDatamartEntity();
          EList<DatamartProperty> _properties_1 = _datamartEntity_3.getProperties();
          for (final DatamartProperty property_1 : _properties_1) {
            AxisEnum _axis_1 = property_1.getAxis();
            String _literal_1 = _axis_1.getLiteral();
            boolean _equals_1 = _literal_1.equals(requestedAxisName);
            if (_equals_1) {
              String _propertyName_1 = this.datamartInferrer.getPropertyName(property_1, null);
              LEntityAttribute _propertyRef_1 = property_1.getPropertyRef();
              IEObjectDescription _create_1 = EObjectDescription.create(_propertyName_1, _propertyRef_1);
              result.add(_create_1);
            }
          }
        }
      }
    }
    EList<DatamartProperty> _properties = entity.getProperties();
    for (final DatamartProperty property : _properties) {
      AxisEnum _axis = property.getAxis();
      boolean _notEquals = (!Objects.equal(_axis, null));
      if (_notEquals) {
        AxisEnum _axis_1 = property.getAxis();
        String _literal = _axis_1.getLiteral();
        boolean _equals = _literal.equals(requestedAxisName);
        if (_equals) {
          String _propertyName = this.datamartInferrer.getPropertyName(property, null);
          LEntityAttribute _propertyRef = property.getPropertyRef();
          IEObjectDescription _create = EObjectDescription.create(_propertyName, _propertyRef);
          result.add(_create);
        }
      } else {
        String _propertyName_1 = this.datamartInferrer.getPropertyName(property, null);
        LEntityAttribute _propertyRef_1 = property.getPropertyRef();
        IEObjectDescription _create_1 = EObjectDescription.create(_propertyName_1, _propertyRef_1);
        result.add(_create_1);
      }
    }
  }
}
