package ip.hak;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.ColorModel;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class HaarLiftingFrame extends ip.gui.frames.ClosableFrame implements ActionListener {
  MenuBar mb = new MenuBar();
  Menu fMenu = new Menu("File");
  MenuItem open_MI, quit_MI;
  Image img = null,xfimg[];
  String fname = null,dir = null;
  RecieveFrame rf;
  short r[][],g[][],b[][];
  Button svButton,sdButton;
  int w, h;


  public static void main(String args[]) {
    HaarLiftingFrame hlf = new HaarLiftingFrame("Haar Lifting Frame");
    hlf.setVisible(true);
  }

  public HaarLiftingFrame(String title) {
    super(title);
    init();
  }

  public void init() {
    setLayout(null);
    int c = 203;
    Color mc = new Color(c, c, c);
    setBackground(mc);
    setSize(380, 320);
    open_MI = new MenuItem("Open Image File..");
    fMenu.add(open_MI);
    open_MI.addActionListener(this);
    quit_MI = new MenuItem("Quit");
    fMenu.add(quit_MI);
    quit_MI.addActionListener(this);
    mb.add(fMenu);
    setMenuBar(mb);

    svButton = new Button("Save");
    svButton.setSize(50, 20);
    svButton.setLocation(300, 100);
    add(svButton);
    svButton.setEnabled(false);
    svButton.addActionListener(this);

    sdButton = new Button("Send");
    sdButton.setSize(50, 20);
    sdButton.setLocation(300, 140);
    add(sdButton);
    sdButton.setEnabled(false);
    sdButton.addActionListener(this);
  }

  public void openFile() {
    FileDialog fd = new FileDialog(this, "Select image file", FileDialog.LOAD);
    fd.setVisible(true);
    fname = fd.getFile();
    if (fname == null) {
      dir = null;
      return;
    }
    dir = fd.getDirectory();
    openImage(dir + fname);
  }

  public void openImage(String fn) {
    img = Toolkit.getDefaultToolkit().getImage(dir + fname);
    repaint();
    waitForImage(this, img);
    image2Short(img);

    if (rf != null)
      rf.dispose();
    rf = new RecieveFrame("Recieve Frame", w, h);
    n = 2;
    ip.gui.Lifting.forwardHaar(r);
    ip.gui.Lifting.forwardHaar(g);
    ip.gui.Lifting.forwardHaar(b);

    svButton.setEnabled(true);
    sdButton.setEnabled(true);
  }

  public void waitForImage(Component component, Image image) {
    MediaTracker tracker = new MediaTracker(component);
    try {
      tracker.addImage(image, 0);
      tracker.waitForID(0);
      if (!tracker.checkID(0))
        System.out.println("Load failure!");
    } catch (InterruptedException e) {
    }
  }

  public void image2Short(Image im) {
    w = im.getWidth(this);
    h = im.getHeight(this);
    r = new short[w][h];
    g = new short[w][h];
    b = new short[w][h];

    int pels[] = new int[w * h];
    ColorModel cm = ColorModel.getRGBdefault();

    PixelGrabber grabber = new PixelGrabber(im, 0, 0, w, h, pels, 0, w);

    try {
      grabber.grabPixels();
    } catch (InterruptedException e) {
    }
    ;

    int i = 0;
    for (int x = 0; x < w; x++)
      for (int y = 0; y < h; y++) {
        i = x + y * w;
        b[x][y] = (short) cm.getBlue(pels[i]);
        g[x][y] = (short) cm.getGreen(pels[i]);
        r[x][y] = (short) cm.getRed(pels[i]);
      }
  }

  public Image short2Image(int wi, int he) {
    Toolkit tk = Toolkit.getDefaultToolkit();
    ColorModel cm = ColorModel.getRGBdefault();

    int pels[] = new int[wi * he];
    for (int x = 0; x < wi; x++)
      for (int y = 0; y < he; y++) {
        pels[x + y * wi] = 0xff000000 | (r[x][y] << 16)
            | (g[x][y] << 8)
            | b[x][y];
      }
    Image i = tk.createImage(new MemoryImageSource(wi, he, cm, pels, 0, wi));
    return i;
  }

  public void paint(Graphics g) {
    Rectangle rec = getBounds();
    if (img == null) {
      g.drawRect(20, rec.height - 276, 256, 256);
      return;
    }

    g.drawImage(img, 20, rec.height - 276, 256, 256, this);

  }

  int n = 1;

  public void send() {
    rf.initArrays();
    rf.sendData(r, g, b, n);
    n *= 2;
    if (n > h) {
      sdButton.setEnabled(false);
      sdButton.transferFocus();
    }
  }

  public void saveFile() {
    FileDialog fd = new FileDialog(this, "Save as lzc file", FileDialog.SAVE);
    fd.setFile("images.lzc");
    fd.setVisible(true);
    String fname = fd.getFile();
    if (fname != null) {
      String dir = fd.getDirectory();
      saveFile(dir + fname);
    }
  }

  public void saveFile(String fn) {
    try {
      FileOutputStream fos = new FileOutputStream(fn);
      ZipOutputStream zos = new ZipOutputStream(fos);
      ObjectOutputStream oos;
      int sn = 0;
      int en = 1;
      int num = 0;
      while (en <= h) {
        ZipEntry ze = new ZipEntry(makeName(num++));
        zos.putNextEntry(ze);
        oos = new ObjectOutputStream(zos);
        saveObject(oos, sn, en);
        sn = en;
        en *= 2;
      }

      zos.finish();
      zos.close();
      System.out.println("Save done...");
    } catch (IOException e) {
      System.out.println(e);
    }
  }

  public String makeName(int i) {
    String name1 = "Datafile";
    String name2 = null;
    if (i < 10)
      name2 = "00" + i + ".dat";
    else if (i < 100)
      name2 = "0" + i + ".dat";
    else
      name2 = "" + i + ".dat";

    return name1 + name2;
  }

  public void saveObject(ObjectOutputStream oos, int sind, int eind) {
    int size = eind - sind;
    short rt[][] = new short[w][size];
    short gt[][] = new short[w][size];
    short bt[][] = new short[w][size];

    for (int x = 0; x < w; x++)
      for (int y = sind,si = 0; y < eind; y++, si++) {
        rt[x][si] = r[x][y];
        gt[x][si] = g[x][y];
        bt[x][si] = b[x][y];
      }
    try {
      oos.writeObject(rt);
      oos.writeObject(gt);
      oos.writeObject(bt);
    } catch (IOException e) {
      System.out.println(e);
    }

  }

  public void actionPerformed(ActionEvent e) {
    if (e.getSource() == open_MI) {
      openFile();
      return;
    }

    if (e.getSource() == quit_MI) {

      dispose();
      return;
    }
    if (e.getSource() == svButton) {
      saveFile();
      return;
    }
    if (e.getSource() == sdButton) {
      send();
      return;
    }
  }
}