/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.uima.ruta.type;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.uima.cas.CAS;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.impl.FeatureStructureImpl;
import org.apache.uima.cas.impl.LowLevelCAS;
import org.apache.uima.cas.impl.TypeImpl;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.JCasRegistry;
import org.apache.uima.jcas.cas.TOP_Type;
import org.apache.uima.jcas.tcas.Annotation;

import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap.Entry;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;

/**
 * 
 * @generated
 */
public class RutaBasic extends Annotation {

  private static final int INITIAL_CAPACITY = 2;

  private static final String ROOT_TYPE1 = CAS.TYPE_NAME_ANNOTATION;

  private static final String ROOT_TYPE2 = CAS.TYPE_NAME_ANNOTATION_BASE;

  private boolean lowMemoryProfile = false;

  private Int2IntOpenHashMap partOf;

  private Int2ObjectOpenHashMap<IntArrayList> beginMap;

  private Int2ObjectOpenHashMap<IntArrayList> endMap;

  private boolean empty = true;

  public boolean isEmpty() {
    return empty;
  }

  public boolean isLowMemoryProfile() {
    return lowMemoryProfile;
  }

  public void setLowMemoryProfile(boolean lowMemoryProfile) {
    this.lowMemoryProfile = lowMemoryProfile;
  }

  public void addPartOf(Type type) {
    int code = ((TypeImpl) type).getCode();
    addPartOf(code);
  }

  private void addPartOf(int code) {
    if (partOf == null) {
      partOf = new Int2IntOpenHashMap();
    }
    partOf.addTo(code, 1);
    if (!lowMemoryProfile) {
      int parentCode = getCAS().getTypeSystem().getLowLevelTypeSystem().ll_getParentType(code);
      if (parentCode > 0) {
        addPartOf(parentCode);
      }
    }
  }

  public void removePartOf(Type type) {
    int code = ((TypeImpl) type).getCode();
    removePartOf(code);
  }

  private void removePartOf(int code) {
    if (partOf != null && partOf.get(code) != 0) {
      partOf.addTo(code, -1);
      if (!lowMemoryProfile) {
        int parentCode = getCAS().getTypeSystem().getLowLevelTypeSystem().ll_getParentType(code);
        if (parentCode > 0) {
          removePartOf(parentCode);
        }
      }
    }
  }

  public boolean isPartOf(Type type) {
    if (partOf == null) {
      return false;
    }
    int code = ((TypeImpl) type).getCode();
    int count = partOf.get(code);
    if (count > 0) {
      return true;
    }
    if (lowMemoryProfile) {
      List<Type> subsumedTypes = getCAS().getTypeSystem().getProperlySubsumedTypes(type);
      for (Type each : subsumedTypes) {
        int code2 = ((TypeImpl) each).getCode();
        int count2 = partOf.get(code2);
        if (count2 > 0) {
          return true;
        }
      }

    }
    return false;

  }

  public void setPartOf(Int2IntOpenHashMap partOf) {
    this.partOf = partOf;
  }

  public Int2IntOpenHashMap getPartOf() {
    return partOf;
  }

  public Collection<AnnotationFS> getBeginAnchors(Type type) {
    if (beginMap == null) {
      return Collections.emptyList();
    }
    int code = ((TypeImpl) type).getCode();
    IntArrayList list = beginMap.get(code);
    if (lowMemoryProfile) {
      Collection<AnnotationFS> result = new ArrayList<AnnotationFS>(list.size());
      if (list != null) {
        result.addAll(adressToAnnotationList(list));
      }
      List<Type> subsumedTypes = getCAS().getTypeSystem().getProperlySubsumedTypes(type);
      for (Type each : subsumedTypes) {
        int parentCode = ((TypeImpl) each).getCode();
        IntArrayList c = beginMap.get(parentCode);
        if (c != null) {
          result.addAll(adressToAnnotationList(c));
        }
      }
      return result;
    } else {
      if (list == null) {
        return Collections.emptySet();
      } else {
        return adressToAnnotationList(list);
      }
    }
  }

  public Collection<AnnotationFS> getEndAnchors(Type type) {
    if (endMap == null) {
      return Collections.emptyList();
    }
    int code = ((TypeImpl) type).getCode();
    IntArrayList list = endMap.get(code);
    if (lowMemoryProfile) {
      Collection<AnnotationFS> result = new ArrayList<AnnotationFS>(list.size());
      if (list != null) {
        result.addAll(adressToAnnotationList(list));
      }
      List<Type> subsumedTypes = getCAS().getTypeSystem().getProperlySubsumedTypes(type);
      for (Type each : subsumedTypes) {
        int parentCode = ((TypeImpl) each).getCode();
        IntArrayList c = endMap.get(parentCode);
        if (c != null) {
          result.addAll(adressToAnnotationList(c));
        }
      }
      return result;
    } else {
      if (list == null) {
        return Collections.emptySet();
      } else {
        return adressToAnnotationList(list);
      }
    }
  }

  public boolean beginsWith(Type type) {
    if (beginMap == null) {
      return false;
    }
    int code = ((TypeImpl) type).getCode();
    Collection<?> set = beginMap.get(code);
    boolean beginsWith = set != null && !set.isEmpty();
    if (beginsWith) {
      return true;
    }
    if (lowMemoryProfile) {
      List<Type> subsumedTypes = getCAS().getTypeSystem().getProperlySubsumedTypes(type);
      for (Type each : subsumedTypes) {
        if (beginsWith(each)) {
          return true;
        }
      }
    }
    return false;
  }

  public boolean endsWith(Type type) {
    if (endMap == null) {
      return false;
    }
    int code = ((TypeImpl) type).getCode();
    Collection<?> set = endMap.get(code);
    boolean endswith = set != null && !set.isEmpty();
    if (endswith) {
      return true;
    }
    if (lowMemoryProfile) {
      List<Type> subsumedTypes = getCAS().getTypeSystem().getProperlySubsumedTypes(type);
      for (Type each : subsumedTypes) {
        if (endsWith(each)) {
          return true;
        }
      }
    }
    return false;
  }

  public void addBegin(AnnotationFS annotation, Type type) {
    if (beginMap == null) {
      beginMap = new Int2ObjectOpenHashMap<>();
    }
    empty = false;
    int code = ((TypeImpl) type).getCode();
    IntArrayList list = beginMap.get(code);
    if (list == null) {
      list = new IntArrayList(INITIAL_CAPACITY);
      beginMap.put(code, list);
    }
    list.add(annotationToAddress(annotation));
    if (!lowMemoryProfile && !type.getName().equals(ROOT_TYPE1)
            && !type.getName().equals(ROOT_TYPE2)) {
      TypeSystem typeSystem = getCAS().getTypeSystem();
      Type parent = typeSystem.getParent(type);
      if (parent != null) {
        addBegin(annotation, parent);
      }
    }
  }

  public void addEnd(AnnotationFS annotation, Type type) {
    if (endMap == null) {
      endMap = new Int2ObjectOpenHashMap<>();
    }
    empty = false;
    int code = ((TypeImpl) type).getCode();
    IntArrayList list = endMap.get(code);
    if (list == null) {
      list = new IntArrayList(INITIAL_CAPACITY);
      endMap.put(code, list);
    }
    list.add(annotationToAddress(annotation));
    if (!lowMemoryProfile && !type.getName().equals(ROOT_TYPE1)
            && !type.getName().equals(ROOT_TYPE2)) {
      TypeSystem typeSystem = getCAS().getTypeSystem();
      Type parent = typeSystem.getParent(type);
      if (parent != null) {
        addEnd(annotation, parent);
      }
    }
  }

  public void removeBegin(AnnotationFS annotation, Type type) {
    if (beginMap == null) {
      return;
    }
    int code = ((TypeImpl) type).getCode();
    IntArrayList list = beginMap.get(code);
    if (list != null) {
      int indexOf = list.indexOf(annotationToAddress(annotation));
      list.removeInt(indexOf);
      if (list.isEmpty()) {
        beginMap.remove(code);
      }
    }
    if (!lowMemoryProfile) {
      TypeSystem typeSystem = getCAS().getTypeSystem();
      Type parent = typeSystem.getParent(type);
      if (parent != null) {
        removeBegin(annotation, parent);
      }
    }
  }

  public void removeEnd(AnnotationFS annotation, Type type) {
    if (endMap == null) {
      return;
    }
    int code = ((TypeImpl) type).getCode();
    IntArrayList list = endMap.get(code);
    if (list != null) {
      int indexOf = list.indexOf(annotationToAddress(annotation));
      list.removeInt(indexOf);
      if (list.isEmpty()) {
        endMap.remove(code);
      }
    }
    if (!lowMemoryProfile) {
      TypeSystem typeSystem = getCAS().getTypeSystem();
      Type parent = typeSystem.getParent(type);
      if (parent != null) {
        removeEnd(annotation, parent);
      }
    }
  }

  public Int2ObjectOpenHashMap<IntArrayList> getBeginMap() {
    return beginMap;
  }

  public Int2ObjectOpenHashMap<IntArrayList> getEndMap() {
    return endMap;
  }

  public void setBeginMap(Int2ObjectOpenHashMap<IntArrayList> beginMap) {
    this.beginMap = beginMap;
    for (Entry<IntArrayList> entry : beginMap.int2ObjectEntrySet()) {
      Collection<?> value = entry.getValue();
      if (value != null && !value.isEmpty()) {
        this.empty = false;
        break;
      }
    }
  }

  public void setEndMap(Int2ObjectOpenHashMap<IntArrayList> endMap) {
    this.endMap = endMap;
    for (Entry<IntArrayList> entry : endMap.int2ObjectEntrySet()) {
      Collection<?> value = entry.getValue();
      if (value != null && !value.isEmpty()) {
        this.empty = false;
        break;
      }
    }
  }

  public void clearBeginMap() {
    this.beginMap.clear();
  }

  public void clearEndMap() {
    this.endMap.clear();
    if (beginMap != null) {
      for (Entry<IntArrayList> entry : beginMap.int2ObjectEntrySet()) {
        Collection<?> value = entry.getValue();
        if (value != null && !value.isEmpty()) {
          return;
        }
      }
    }
    this.empty = true;
  }

  private Collection<AnnotationFS> adressToAnnotationList(IntArrayList addressList) {
    List<AnnotationFS> result = new ArrayList<>(addressList.size());
    for (int value : addressList) {
      result.add(addressToAnnotation(value));
    }
    return result;
  }

  private int annotationToAddress(AnnotationFS annotation) {
    return ((FeatureStructureImpl) annotation).getAddress();
  }

  private AnnotationFS addressToAnnotation(int address) {
    LowLevelCAS lowLevelCAS = getCASImpl().getLowLevelCAS();
    FeatureStructure fs = lowLevelCAS.ll_getFSForRef(address);
    return (AnnotationFS) fs;
  }

  /**
   * @generated
   * @ordered
   */
  public final static int typeIndexID = JCasRegistry.register(RutaBasic.class);

  /**
   * @generated
   * @ordered
   */
  public final static int type = typeIndexID;

  /** @generated */
  @Override
  public int getTypeIndexID() {
    return typeIndexID;
  }

  /**
   * Never called. Disable default constructor
   * 
   * @generated
   */
  protected RutaBasic() {/* intentionally empty block */
  }

  /**
   * Internal - constructor used by generator
   * 
   * @generated
   */
  public RutaBasic(int addr, TOP_Type type) {
    super(addr, type);
    readObject();
  }

  /** @generated */
  public RutaBasic(JCas jcas) {
    super(jcas);
    readObject();
  }

  /** @generated */
  public RutaBasic(JCas jcas, int begin, int end) {
    super(jcas);
    setBegin(begin);
    setEnd(end);
    readObject();
  }

  /**
   * <!-- begin-user-doc --> Write your own initialization here <!-- end-user-doc -->
   * 
   * @generated modifiable
   */
  private void readObject() {
  }

  // *--------------*
  // * Feature: Replacement

  /**
   * getter for Replacement - gets
   * 
   * @generated
   */
  public String getReplacement() {
    if (RutaBasic_Type.featOkTst && ((RutaBasic_Type) jcasType).casFeat_replacement == null)
      jcasType.jcas.throwFeatMissing("replacement", "org.apache.uima.ruta.type.RutaBasic");
    return jcasType.ll_cas.ll_getStringValue(addr,
            ((RutaBasic_Type) jcasType).casFeatCode_replacement);
  }

  /**
   * setter for Replacement - sets
   * 
   * @generated
   */
  public void setReplacement(String v) {
    if (RutaBasic_Type.featOkTst && ((RutaBasic_Type) jcasType).casFeat_replacement == null)
      jcasType.jcas.throwFeatMissing("replacement", "org.apache.uima.ruta.type.RutaBasic");
    jcasType.ll_cas.ll_setStringValue(addr, ((RutaBasic_Type) jcasType).casFeatCode_replacement, v);
  }

}
