/*
 * 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 opennlp.tools.coref.DiscourseEntity;
import opennlp.tools.coref.DiscourseModel;
import opennlp.tools.coref.mention.MentionContext;
import opennlp.tools.coref.mention.Parse;
import opennlp.tools.util.CountedSet;

/**
 * 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 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 CountedSet<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 CountedSet<Integer>();
  }

  /**
   * 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()) {
        distances.add(ei);
        return cde;
      }
    }
    //System.err.println("AbstractResolver.retain: non-refering 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 {};
}
