package yi.iu.processor.texture.laws;

import java.awt.*;

import yi.iu.processor.channel.*;
import yi.util.config.*;
import yi.util.io.*;
import yi.util.io.input.*;
import yi.util.io.output.*;
import yi.util.log.*;


/**
 * Class DPU_Laws is helper function to provide configurable and reusable
 * feature for class Laws.  If you want to use those features, use this class
 * instead of Laws
 */
public class DPU_Laws extends Laws implements Configurable, RstReusable{

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

  public int    REUSE  = DIU.INPUT_SER;
  public int    OUTPUT = DOU.OUTPUT_SER;

  public int    LOG_LEVEL = 3;

  public String[] getParameterNames() {
    return new String[] {
      "PRE_SMOOTH_WIN_WIDTH",
      "PRE_SMOOTH_WIN_HEIGHT",
      "POST_SMOOTH_WIN_WIDTH",
      "POST_SMOOTH_WIN_HEIGHT",
      "LOG_LEVEL",
      "REUSE",
      "OUTPUT",
      "DEMO_AVERAGED",
      "DEMO_CONVOLUTED",
      "DEMO_POST_SMOOTHED",
      "DEMO_MASK",
      "DEMO_TEXTURE_ENERGY_MEASURES"
    };
  }

  int m_reuseFrom;
  public Object reuse(int reuse_level) {
    m_reuseFrom = DIU.INPUT_NONE;
    if (reuse_level != DIU.INPUT_NONE) {
      try {
        // only serializer is supported for this class
        if (reuse_level != DIU.INPUT_SER) {
          throw new DataInputException("reuse method " + reuse_level +
            "is not supported by DPU_Laws");
        }
        int[][][] rst = (int[][][])DIU.in(
            reuse_level,
            DOU.shortName(this.getClass().getName()),
            "EnergyMeasures",
            null);
        if (rst != null) m_reuseFrom = reuse_level;
        return rst;
      }
      catch (Exception e) {
        LogHandler.log(this, LOG_LEVEL, 1, "Can't Reuse Energy Measures:\n" + e);
      }
    }
    return null;
  }

  public void output(int output_level, int[][][] ds){
    if (output_level != DOU.OUTPUT_NONE) {
      try {
        // only serializer is supported for this class
        if (output_level != DOU.OUTPUT_SER) {
          throw new DataOutputException("output method " + output_level +
            "is not supported by DPU_Laws");
        }
        DOU.out(
            output_level & (~ m_reuseFrom),
            DOU.shortName(this.getClass().getName()),
            "EnergyMeasures",
            ds);
      } catch (DataOutputException e) {
        LogHandler.log(this, LOG_LEVEL, 1, e.toString());
      }
    }
  }

  public int[][][] getTextureEnergyMeasures(int[][] grays, int width, int height) {
      int[][][] rst = (int[][][])reuse(REUSE);

      if (rst == null) {
        rst = super.getTextureEnergyMeasures(grays, width, height);
      }

      output(OUTPUT, rst);

      return rst;

  }

  public static void main(String[] args) {
    // init configuration
    Configuration.init(args);

    // get the image name
    String img_name = ReadArgu.getOption('i', args);
    if (img_name == null) {
      System.err.println("Usage: -i image_name");
      System.exit(1);
    }

    // read in image
    Image image = null;
    Dimension d = new Dimension();
    int[] pixels = null;
    try {
      image = yi.util.io.ImageReader.readImageFile(img_name);
      pixels = yi.util.io.ImageReader.getPixels(image, d);
    }
    catch (java.io.IOException e) {
      System.err.println("Can't read image " + img_name);
      e.printStackTrace();
      System.exit(2);
    }

    // process
    // change to 2D gray level image first
    pixels = CYMaker.getLuminance(pixels, d);               // change to gray
    int[][] pixels2D = yi.util.ImageUtil.oneD2twoD(pixels, d);  // change to 2D
    Configuration.setParameter("SOURCE_NAME", img_name);
    DPU_Laws dp = new DPU_Laws();
    long startTime = System.currentTimeMillis();
    int[][][] rst = dp.getTextureEnergyMeasures(pixels2D, d.width, d.height);
    long endTime = System.currentTimeMillis();
    System.out.println("running time: " + (endTime-startTime));

    int[] maximum = new int[rst.length];
    for (int h =0; h<d.height; h++) {
      for (int w=0; w<d.width; w++) {
        for (int i=0;i<rst.length;i++) {
          if (rst[i][h][w] > maximum[i]) maximum[i] = rst[i][h][w];
        }
      }
    }
    for (int i=0;i<maximum.length;i++) {
      System.out.print(maximum[i]);
      System.out.print(",");
    }
    System.out.println();

    System.exit(0);
  }

}