import java.awt.image.*;
import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;
import Acme.JPM.Encoders.*;

public class LineUp extends Canvas {
  ImArray ima, imb;
  cornerTransform cur, drawthis;
  int curscale;
  Frame f;

  public static void main(String args[]){
    LineUp lu = new LineUp();
    lu.doIt(args);
  }

  void doIt(String args[]){
    ima = StillUtil.loadImage(args[0]);
    imb = StillUtil.loadImage(args[1]);

    f = new Frame();
    f.add(this);
    f.setBounds(0,0,500,500);
    f.doLayout();
    f.show();
    cur = new cornerTransform(ima);
    drawthis = cur;
    repaint();
    //    (new repaintThread(this)).start();
    try {
      if(args.length > 2){
	cur = cur.translate(Integer.parseInt(args[2]), Integer.parseInt(args[3]));
	drawthis = cur;
      }
    } catch (Exception e) { }
    cur = findTranslationalMinimum(ima, imb, cur);
    cur = wiggleCorners(ima, imb, cur);
    StillUtil.writeMerge(ima, imb, cur);

    System.out.println("All Done");

  }

  cornerTransform findTranslationalMinimum(ImArray ima, 
					  ImArray imb, 
					  cornerTransform t){
    cornerTransform best, temp, pass, st;
    double bd, d;
    ImArray sima, simb;

    sima = ima.shrink(10);
    simb = imb.shrink(10);
    st = t.shrink(10);
    curscale = 10;
    best = StillUtil.anneal(sima, simb, st, 30.0, 12, 20.0, true);
    best = StillUtil.anneal(sima, simb, best, 20.0, 6, 10.0, true);
    best = StillUtil.anneal(sima, simb, best, 20.0, 2, 10.0, true);
    best = StillUtil.downhill(sima, simb, best, 10, 4, true);
    best = StillUtil.downhill(sima, simb, best, 10, 2, true);
    best = StillUtil.downhill(sima, simb, best, 10, 1, true);
    sima = ima.shrink(4);
    simb = imb.shrink(4);
    best = best.grow(10);
    best = best.shrink(4);
    curscale = 4;
    best = StillUtil.anneal(sima, simb, best, 15.0, 6, 5.0, true);
    best = StillUtil.anneal(sima, simb, best, 10.0, 2, -5.0, true);
    best = StillUtil.downhill(sima, simb, best, 10, 2, true);
    best = StillUtil.downhill(sima, simb, best, 10, 1, true);
    best = best.grow(4);

    sima = ima.shrink(2);
    simb = imb.shrink(2);
    best = best.shrink(2);
    curscale = 2;
    best = StillUtil.anneal(sima, simb, best, 10.0, 2, -1, true);
    best = StillUtil.downhill(sima, simb, best, 10, 1, true);
    best = best.grow(2);
    curscale = 1;

    best = StillUtil.anneal(ima, imb, best, 0.0, 4, -1.0, true);
    best = StillUtil.downhill(ima, imb, best, 10, 1, true);
    System.out.println("Done with StillUtil.annealing\n");

    bd = ImArray.imageDifference(ima, imb, best);
    System.out.println("findTranslationalMinimum is done with a difference of "+bd);

    return best;
  }

  cornerTransform wiggleCorners(ImArray ima, ImArray imb, cornerTransform t){
    cornerTransform best;
    best = t;
    System.out.println("Wiggling corners now...");
    best = StillUtil.anneal(ima, imb, best, 5.0, 3, -10.0, false);
    best = StillUtil.downhill(ima, imb, best, 20, 8, false);
    best = StillUtil.downhill(ima, imb, best, 20, 4, false);
    best = StillUtil.downhill(ima, imb, best, 20, 2, false);
    best = StillUtil.downhill(ima, imb, best, 20, 1, false); 
   return best;
  }
  public void paint(Graphics g){
    cornerTransform dt = null;

    dt = drawthis.copy();
    dt.grow(curscale);

    g.setColor(Color.black);
    g.fillArc(-10, -10, 20, 20, 0, 360);
    g.fillArc(-10, ima.height-10, 20, 20, 0, 360);
    g.fillArc(ima.width-10, -10, 20, 20, 0, 360);
    g.fillArc(ima.width-10, ima.height-10, 20, 20, 0, 360);
    g.setColor(Color.red);
    g.fillArc((int) (dt.x0)-10, (int) (dt.y0)-10, 20, 20, 0, 360);
    g.fillArc((int) (dt.x1)-10, (int) (dt.y1)-10, 20, 20, 0, 360);
    g.fillArc((int) (dt.x2)-10, (int) (dt.y2)-10, 20, 20, 0, 360);
    g.fillArc((int) (dt.x3)-10, (int) (dt.y3)-10, 20, 20, 0, 360);
  }
}
