package yi.iu.processor.cluster;

import yi.iu.processor.*;
import yi.iu.processor.channel.CYMaker;
import yi.util.io.OutputResult;
import yi.iu.ui.DisplayFrame;
import yi.util.io.ImageReader;

import java.awt.*;
import java.util.Random;
import yi.util.io.*;

/**
 * Color segmentattion in the CY-HSI color space using the K-means cluster
 * algorithm
 *
 * There are several different init method could be use for K-means cluster
 * random, linear, cube, statistical, possbility, predefined
 * (possibility is not finished yet)
 *
 * [REFERENCE]
 *   A. R. Weeks, Color segmentation in the HSI color space using the K-means
 *   algorithm
 */
public class CYColorKMCluster extends yi.iu.processor.ImageProcessor
{
    // possible type of returned result
    public final static int RT_LABEL = 0;   // return the label of region
    public final static int RT_COLOR = 1;   // return the mean of the color
                                            // of the regions
    KMCluster cluster = null;               // K means cluster instance

    // arguments for K means
    int k;
    int initMethod;
    int returnType = RT_LABEL;              // return type (label/mean color)

    public int getArguNum() { return 1;}

    public void setArgument(int i, String st)
    {
        if (st.length()==0) return;
        if (i==1) initMethod= Integer.valueOf(st).intValue();
    }

    public String getArgument(int i)
    {
        if (i==0) return (new Integer(initMethod)).toString();
        return null;
    }

    public String getArguName(int i)
    {
        if (i==0) return "Init Method";
        return null;
    }


    public CYColorKMCluster() { super();}

    public CYColorKMCluster(int k, int initMethod, int result_type) {
        this();
        this.k = k;
        this.initMethod = initMethod;
        this.returnType = result_type;
    }

    /**
     * Main function to get the resultant clusters
     * [EFFECTS]
     *   using HSI color space, so getMeans will return mean HSI
     * [EXAMPLE]
     *   KMCluster c =  CYColorKMCluster.getCluster(k,
     *                                              KMCluster.LINEAR,
     *                                              pixels);
     *   int[] labels = c.getLabels();
     *   int[] colors = c.getMeans();
     */
    public static KMCluster getCluster(int k, int initMethod, int source[]) {
        Dimension d = new Dimension (source.length, 1);        // doesn' matter
        int[][] hsi= (new CYMaker()).getProcessed_ex(source, d);
        return new KMCluster(k, initMethod, hsi);
    }

    public int[] getProcessed(int source[], Dimension d)
    {
        int[][] info= (new CYMaker()).getProcessed_ex(source, d);
        cluster = new KMCluster(k, initMethod, info);
        int[] rst= cluster.getLabels();
        return rst;
    }

    public int[] getProcessedPseudoColor(int source[], Dimension d)
    {
        if (returnType==RT_LABEL) {
            int[] label= getProcessed(source,d);
            int[] rst= yi.util.ImageUtil.makeNewImageFromLabel(label);
//            int[][] label_2= yi.util.ImageUtil.oneD2twoD(label, d);
//            yi.or.Region r= new yi.or.Region(label_2);
//            r.display();
            //OutputResult.outputResult("means", init_means);
            return rst;
        }
        else if (returnType==RT_COLOR) {
            int[] label = getProcessed(source,d);
            int[][] means = cluster.getMeans();
            int size = label.length;
            for (int i=0; i<size; i++) {
                int l=label[i];
                int h=means[l][0],s=means[l][1],y=means[l][2];
                int rgb=CYMaker.hsi2rgb(h, s, y);
                    label[i]= rgb;
            }

            (new DisplayFrame("mean_color", label, d)).show();
            return label;
        }
        else return null;
    }

    public static void main(String[] args) {
      // get the image name
      String img_name = yi.util.io.ReadArgu.getOption('i', args);
      if (img_name == null) {
        System.err.println("Usage: -i image_name");
        System.exit(1);
      }

      // read in image
      // get the scale
      String k_str = ReadArgu.getOption('k', args, "16");
      int k = Integer.parseInt(k_str);


        // read image
        try {
          Image im = ImageReader.readImageFile(img_name);
          Dimension d = new Dimension();
          int[] rgb = ImageReader.getPixels(im, d);

          // K means cluster using CY-HSI color space
          CYColorKMCluster c = new CYColorKMCluster(k,   // k
                           KMCluster.RANDOM,
                           RT_COLOR);
          int[] labels = c.getProcessed(rgb, d);
          int[] label_img = yi.util.ImageUtil.makeNewImageFromLabel(labels, false);
          yi.util.io.OutputResult.outputGIFImage(img_name + ".kmeans.gif", label_img, d.width, d.height, false);
        } catch (java.io.IOException e) {
          e.printStackTrace();
        }
    }
}