package yi.iu.processor.clc;

import java.awt.*;
import java.util.*;

import yi.ds.*;
import yi.iu.processor.ort.*;
import yi.iu.region.*;
import yi.util.config.*;
import yi.util.io.*;
import yi.util.io.input.*;
import yi.util.io.output.*;
import yi.util.log.*;

/**
 * Construct Orientation Consistent Line Cluster.
 */
public class CLC_Intrarelationship extends CLC_Clustering{

  public double OVERLAP_THRESHOLD = 5;
  public boolean PRE_RE_CLUSTERING = false;

  public CLC_Intrarelationship() {
    Configuration.configParameters(this);
  }

  public String[] getParameterNames() {
    return super.getParameterNames(new String[] {
                                   "OVERLAP_THRESHOLD",
                                   "PRE_RE_CLUSTERING"
    });
  }

  /**
   * Pre re-clustering the line clusters with more restricted criterions by
   * color, orientation, position, length
   * @param clusters
   * @return
   */
  private LineClusterSets preReClustering(LineClusterSets clusters, int[] rgb, int width, int height) {

    // for output demo images
    String img_name = Configuration.getStringParameter("SOURCE_NAME", "");
    String prefix = img_name + "." +
        yi.util.data.Conversion.toString(++output_counter, 2);

    // Filter the lines using orientation (Although the lines were clustered by
    // orientation already, the resultant clusters were then clustered by
    // spatial info.  So another step of orientation may help)
    CLC_Orientation clc_orientation = new CLC_Orientation();
    clusters = clc_orientation.getClusters(clusters, rgb, width, height);
    if (DEMO_STEPS) {
      clusters.outputClustersOneByOne(rgb, new Dimension(width, height), prefix + ".b", false);
    }

    // more strict vertical position based clustering
    CLC_VerticalPosition clc_vertical = new CLC_VerticalPosition();
    clc_vertical.SUSPENSION_TOWER_ABILITY = 0.25;
    clusters = clc_vertical.getClusters(clusters, rgb, width, height);
    if (DEMO_STEPS) {
      clusters.outputClustersOneByOne(rgb, new Dimension(width, height), prefix + ".c", false);
    }

    // more strict horizontal position based clustering
    CLC_HorizontalPosition clc_horizontal = new CLC_HorizontalPosition();
    clc_horizontal.MIN_HIST_BREAKING_TOLERANCE = 0;
    clc_horizontal.TOLERANCE_2_AVERAGE_LEN = 1.2;
    clusters = clc_horizontal.getClusters(clusters, rgb, width, height);
    if (DEMO_STEPS) {
      clusters.outputClustersOneByOne(rgb, new Dimension(width, height), prefix + ".d", false);
    }

//    // length based clustering
//    CLC_Length clc_length = new CLC_Length();
//    clusters = clc_length.getClusters(clusters, rgb, width, height);
//    if (DEMO_STEPS) {
//      clusters.outputClustersOneByOne(rgb, new Dimension(width, height), prefix + ".e", false);
//    }

    return clusters;
  }

  public LineClusterSets getClusters(LineClusterSet lines, int[] rgb, int width, int height) {

    LineClusterSets clusters = new LineClusterSets(width, height);
    clusters.put(lines, lines);

    if (PRE_RE_CLUSTERING) {
      clusters = preReClustering(clusters, rgb, width, height);
    }

    // new line cluster sets
    LineClusterSets results = new LineClusterSets(width, height);

    // deal with each LineClusterSet one by one
    Iterator i = clusters.values().iterator();
    while (i.hasNext()) {
      LineClusterSet lc = (LineClusterSet)i.next();
      int size0 = lc.size();
      Intrarelationship intrarelation = Intrarelationship.intrarelation2(lc, OVERLAP_THRESHOLD);
      int size1 = intrarelation.m_overlappingLineNum;
      lc = intrarelation.m_overlappingLines;
      intrarelation = Intrarelationship.intrarelation2(lc, OVERLAP_THRESHOLD);
      int size2 = intrarelation.m_overlappingLineNum;
      if (intra_related(size0, intrarelation)) {
        results.put(intrarelation.m_overlappingLines, intrarelation.m_overlappingLines);
        if (SHOW_PROGRESS) {
          System.out.println("cluster size " + size0 + " -> " + size1 + " -> " +
                             size2);
          System.out.println(results);
        }
      }
    }

    // filter the result
    results.filter(
      CLCConfig.getMinQualifiedLineLen(),
      CLCConfig.getMinQualifiedCLCLineLenSum(width, height));

    // inherit the properties from the parent (clustered from)
    results.inheritProperties(lines);

    return results;
  }

  boolean intra_related(Intrarelationship r) {
    return r.m_overlappingLineNum > 0;



  }

  boolean intra_related(int cluster_size, Intrarelationship r) {
    int overlapped = r.m_overlappingLineNum;
    if (cluster_size > 5 && overlapped > cluster_size * 0.5)
      return true;
    if (cluster_size > 15 && overlapped > cluster_size * 0.33)
      return true;
    return false;
  }

  /**
   * Determine whether this is a intra-related cluster.  The cluster_size is
   * the size of the cluster and in intrarelationship r, there are the number
   * of overlapped lines.  This is a temporary solution to get in the old
   * intra-relationship criteria
   * @param cluster_size
   * @param r
   * @return
   */
//  boolean intra_related(int cluster_size, Intrarelationship r) {
//    int overlapped = r.m_overlappingLineNum;
//    if (overlapped > 8 && overlapped > cluster_size * 0.8) return true;
//    if (overlapped > 14 && overlapped > cluster_size * 0.6) return true;
//    if (overlapped > 30 && overlapped > cluster_size * 0.31) return true;
//    return false;
//
//  }


  /**
   * After got all the intra-related line clusters.  The post process will merge
   * those clusters close to each other.
   * @param line_clusters
   * @param rgb
   * @param width
   * @param height
   * @return
   */
  public LineClusterSets postProcess(LineClusterSets line_clusters, int[] rgb, int width, int height) {
//    line_clusters = LineClusterSets.mergeThoseHaveCommon(line_clusters);
    return line_clusters;
  }

}