/*
 * 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.cas.impl;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.uima.UIMAFramework;
import org.apache.uima.cas.CAS;
import org.apache.uima.resource.metadata.FsIndexDescription;
import org.apache.uima.resource.metadata.TypeSystemDescription;
import org.apache.uima.test.junit_extension.JUnitExtension;
import org.apache.uima.util.CasCreationUtils;
import org.apache.uima.util.XMLInputSource;
import org.junit.jupiter.api.Test;

/**
 * Testclass for the JTok annotator.
 */
public class UnambiguousIteratorTest {

  private static final String casDataDirName = "CASTests";

  private static final String xcasSampleDirName = "xcas";

  private static final String sampleXcas1FileName = "sample1.xcas";

  private static final String sampleXcas2FileName = "sample2.xcas";

  private static final String sampleTsFileName = "sample.ts";

  @Test
  public void testUnambiguous() throws Exception {

    // The two XCASes used in this test contain the same data, but the
    // second one contains all annotations twice. So in that case, every
    // other annotation is filtered by the unambiguous iterator.

    File dataDir = JUnitExtension.getFile(casDataDirName);
    File xcasDir = new File(dataDir, xcasSampleDirName);

    try {

      File tsFile = new File(xcasDir, sampleTsFileName);
      Object descriptor = UIMAFramework.getXMLParser().parse(new XMLInputSource(tsFile));
      // instantiate CAS to get type system. Also build style
      // map file if there is none.
      TypeSystemDescription tsDesc = (TypeSystemDescription) descriptor;
      CAS cas = CasCreationUtils.createCas(tsDesc, null, new FsIndexDescription[0]);

      SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
      XCASDeserializer xcasDeserializer = new XCASDeserializer(cas.getTypeSystem());
      File xcasFile = new File(xcasDir, sampleXcas1FileName);
      parser.parse(xcasFile, xcasDeserializer.getXCASHandler(cas));

      /*
       * // Create an XML input source from the specifier file. XMLInputSource in = new
       * XMLInputSource(this.tafDataDir + "specifiers/jtok.xml"); // Parse the specifier.
       * ResourceSpecifier specifier = UIMAFramework.getXMLParser() .parseResourceSpecifier(in); //
       * Create the Text Analysis Engine. tae = UIMAFramework.produceTAE(specifier, null, null); //
       * Create a new CAS. CAS cas = tae.newCAS(); // Set the document text on the CAS.
       * cas.setDocumentText(text); cas.setDocumentLanguage("en"); // Process the sample document.
       * tae.process(cas); System.out.println("Annotation index size: " +
       * cas.getAnnotationIndex().size());
       */
      LowLevelCAS llc = cas.getLowLevelCAS();
      final int tokType = llc.ll_getTypeSystem().ll_getCodeForTypeName("uima.tt.TokenAnnotation");
      LowLevelIndex annotIdx = llc.ll_getIndexRepository().ll_getIndex(CAS.STD_ANNOTATION_INDEX,
              tokType);
      final int annotSizeA1 = iteratorSize(annotIdx.ll_iterator());
      final int annotSizeU1 = iteratorSize(annotIdx.ll_iterator(false));
      assertEquals(annotSizeA1, annotSizeU1);

      parser = SAXParserFactory.newInstance().newSAXParser();
      xcasDeserializer = new XCASDeserializer(cas.getTypeSystem());
      xcasFile = new File(xcasDir, sampleXcas2FileName);
      parser.parse(xcasFile, xcasDeserializer.getXCASHandler(cas));

      annotIdx = llc.ll_getIndexRepository().ll_getIndex(CAS.STD_ANNOTATION_INDEX, tokType);
      final int annotSizeA2 = iteratorSize(annotIdx.ll_iterator());
      final int annotSizeU2 = iteratorSize(annotIdx.ll_iterator(false));
      // System.out.println("Annotation index size: "
      // + cas.getAnnotationIndex().size());
      // System.out.println("U1: " + annotSizeU1);
      // System.out.println("A1: " + annotSizeA1);
      // System.out.println("U2: " + annotSizeU2);
      // System.out.println("A2: " + annotSizeA2);
      assertEquals(annotSizeU1, annotSizeU2);
      assertTrue(annotSizeA2 > annotSizeU2);
      assertEquals(annotSizeA2, annotSizeU2 * 2);

      annotIdx = llc.ll_getIndexRepository().ll_getIndex(CAS.STD_ANNOTATION_INDEX,
              ((TypeImpl) (cas.getAnnotationType())).getCode());
      iteratorSize(annotIdx.ll_iterator());
      iteratorSize(annotIdx.ll_iterator(false));
    } catch (Exception ex) {
      JUnitExtension.handleException(ex);
    }

  }

  private static final int iteratorSize(LowLevelIterator it) {
    int size = 0;
    for (it.moveToFirst(); it.isValid(); it.moveToNext()) {
      ++size;
    }
    assertEquals(size, it.ll_indexSizeMaybeNotCurrent());
    return size;
  }

}
