/*
 * 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 opennlp.tools.coref.resolver;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import opennlp.tools.coref.DiscourseEntity;
import opennlp.tools.coref.DiscourseModel;
import opennlp.tools.coref.mention.MentionContext;
import opennlp.tools.coref.mention.Parse;

/**
 * Default implementation of some methods in the {@link Resolver} interface.
 */
public abstract class AbstractResolver implements Resolver {

  /** 
   * The number of previous entities that resolver should consider.
   */
  protected final int numEntitiesBack;
  
  /** 
   * Debugging variable which specifies whether error output is generated
   * if a class excludes as possibly coreferent mentions which are in-fact
   * coreferent.
   */
  protected boolean showExclusions;
  
  /** 
   * Debugging variable which holds statistics about mention distances
   * during training.
   */
  protected final Map<Integer, Integer> distances;
  
  /** 
   * The number of sentences back this resolver should look for a referent.
   */
  protected int numSentencesBack;

  public AbstractResolver(int neb) {
    numEntitiesBack = neb;
    showExclusions = true;
    distances = new HashMap<>();
  }

  /**
   * Returns the number of previous entities that resolver should consider.
   * 
   * @return the number of previous entities that resolver should consider.
   */
  protected int getNumEntities() {
    return numEntitiesBack;
  }

  /**
   * Specifies the number of sentences back this resolver should look for a referent.
   * 
   * @param nsb the number of sentences back this resolver should look for a referent.
   */
  public void setNumberSentencesBack(int nsb) {
    numSentencesBack = nsb;
  }

  /**
   * The number of entities that should be considered for resolution with the specified discourse model.
   * 
   * @param dm The discourse model.
   * 
   * @return number of entities that should be considered for resolution.
   */
  protected int getNumEntities(DiscourseModel dm) {
    return Math.min(dm.getNumEntities(),numEntitiesBack);
  }

  /**
   * Returns the head parse for the specified mention.
   * 
   * @param mention The mention.
   * 
   * @return the head parse for the specified mention.
   */
  protected Parse getHead(MentionContext mention) {
    return mention.getHeadTokenParse();
  }

  /**
   * Returns the index for the head word for the specified mention.
   * 
   * @param mention The mention.
   * 
   * @return the index for the head word for the specified mention.
   */
  protected int getHeadIndex(MentionContext mention) {
    Parse[] mtokens = mention.getTokenParses();
    for (int ti = mtokens.length - 1; ti >= 0; ti--) {
      Parse tok = mtokens[ti];
      if (!tok.getSyntacticType().equals("POS") && !tok.getSyntacticType().equals(",") &&
          !tok.getSyntacticType().equals(".")) {
        return ti;
      }
    }
    return mtokens.length - 1;
  }

  /**
   * Returns the text of the head word for the specified mention.
   * 
   * @param mention The mention.
   * 
   * @return The text of the head word for the specified mention.
   */
  protected String getHeadString(MentionContext mention) {
    return mention.getHeadTokenText().toLowerCase();
  }

  /**
   * Determines if the specified entity is too far from the specified mention to be resolved to it.
   * Once an entity has been determined to be out of range subsequent entities are not considered.
   * To skip intermediate entities @see excluded.
   * 
   * @param mention The mention which is being considered.
   * @param entity The entity to which the mention is to be resolved.
   * 
   * @return true is the entity is in range of the mention, false otherwise.
   */
  protected boolean outOfRange(MentionContext mention, DiscourseEntity entity) {
    return false;
  }

  /**
   * Excludes entities which you are not compatible with the entity under consideration. The default
   * implementation excludes entities whose last extent contains the extent under consideration.
   * This prevents possessive pronouns from referring to the noun phrases they modify and other
   * undesirable things.
   * 
   * @param mention The mention which is being considered as referential.
   * @param entity The entity to which the mention is to be resolved.
   * 
   * @return true if the entity should be excluded, false otherwise.
   */
  protected boolean excluded(MentionContext mention, DiscourseEntity entity) {
    MentionContext cec = entity.getLastExtent();
    return mention.getSentenceNumber() == cec.getSentenceNumber() &&
        mention.getIndexSpan().getEnd() <= cec.getIndexSpan().getEnd();
  }

  public DiscourseEntity retain(MentionContext mention, DiscourseModel dm) {
    int ei = 0;
    if (mention.getId() == -1) {
      return null;
    }
    for (; ei < dm.getNumEntities(); ei++) {
      DiscourseEntity cde = dm.getEntity(ei);
      MentionContext cec = cde.getLastExtent(); // candidate extent context
      if (cec.getId() == mention.getId()) {
        // incrementing count for key 'ei'
        distances.merge(ei, 1, Integer::sum);
        return cde;
      }
    }
    //System.err.println("AbstractResolver.retain: non-referring entity with id: "+ec.toText()+" id="+ec.id);
    return null;
  }

  /**
   * Returns the string of "_" delimited tokens for the specified mention.
   * 
   * @param mention The mention.
   * 
   * @return the string of "_" delimited tokens for the specified mention.
   */
  protected String featureString(MentionContext mention) {
    StringBuilder fs = new StringBuilder();
    Object[] mtokens = mention.getTokens();
    fs.append(mtokens[0].toString());
    for (int ti = 1, tl = mtokens.length; ti < tl; ti++) {
      fs.append("_").append(mtokens[ti].toString());
    }
    return fs.toString();
  }


  public void train() throws IOException {}
}
