package ip.raul;

import ip.gui.dialog.DoubleLog;
import ip.gui.frames.ImageFrame;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;

import futils.Futil;


public class Editor3D extends ImageFrame
    implements ActionListener, ItemListener {

  MenuBar mb = new MenuBar();
  Menu ModelMenu = new Menu("Model");
  Menu WindowMenu = new Menu("Window");
  Menu ViewsMenu = new Menu("Views");

  MenuItem props_mi = addMenuItem(ModelMenu, "[s]how object info");
  MenuItem save_mi = addMenuItem(ModelMenu, "[S]ave scene");
  MenuItem open_mi = addMenuItem(ModelMenu, "[O]pen scene");
  MenuItem texture_mi = addMenuItem(ModelMenu, "[T] Add texture");
  MenuItem sphere_mi = addMenuItem(ModelMenu, "[1] sphere");
  MenuItem cylinder_mi = addMenuItem(ModelMenu, "[2] cylinder");
  MenuItem paralelipiped_mi = addMenuItem(ModelMenu, "[3] Paralelipiped");
  MenuItem snowman_mi = addMenuItem(ModelMenu, "[4] snowMan");

  MenuItem frontview_mi = addMenuItem(ViewsMenu, "Front");
  MenuItem backview_mi = addMenuItem(ViewsMenu, "Back");
  MenuItem leftview_mi = addMenuItem(ViewsMenu, "Left");
  MenuItem rightview_mi = addMenuItem(ViewsMenu, "Right");
  MenuItem topview_mi = addMenuItem(ViewsMenu, "Top");
  MenuItem bottomview_mi = addMenuItem(ViewsMenu, "Bottom");

  MenuItem threeD_mi = addMenuItem(ViewsMenu, "Full 3D mode");

  static int maxALL = 20;
  private Object3D objects[] = new Object3D[maxALL];
  private String textures[] = new String[maxALL];
  Image img = null;
  private int maxTextures = -1;
  private int maxObjects = -1;
  private int objectType = 1;
  ObjectInfo oi = null;
  DoubleLog DLog = null;
  private ObjectView front = null;
  private ObjectView back = null;
  private ObjectView top = null;
  private ObjectView bottom = null;
  private ObjectView left = null;
  private ObjectView right = null;
  private SnowMan _3D = null;
  public boolean busyView = false;
  public int indexView = 1;

  public void itemStateChanged(ItemEvent e) {
    if (e.getSource() == oi.names) {
      indexView = oi.names.getSelectedIndex();
      busyView = true;
      updateViews();
      return;
    }
  }

  public void actionPerformed(ActionEvent e) {
    try {
      Button b = (Button) e.getSource();
      if (b == oi.setButton) {
        objects = oi.objects;
        for (int i = 0; i <= maxObjects; i++) {
          if (objects[i].textureIndex >= 0)
            objects[i].Texture = textures[objects[i].textureIndex];
        }
        busyView = false;
        updateViews();
      }
      if (b == oi.cancelButton) {
        busyView = false;
        updateViews();
      }
    } catch (Exception ex) {
    }
    try {
      Button b = (Button) e.getSource();
      if (b == DLog.setButton) {
        double d[] = DLog.getUserInputAsDouble();
        switch (objectType) {
          case 1:
            addSphere(d[0], d[1], d[2], d[3]);
            break;
          case 2:
            addCylinder(d[0], d[1], d[2], d[3], d[4]);
            break;
          case 3:
            addParalelipiped(d[0], d[1], d[2], d[3], d[4], d[5]);
            break;
        }
        updateViews();
      }
    } catch (Exception ex) {
    }
    if (match(e, texture_mi)) {
      maxTextures++;
      String fn = Futil.getReadFileName();
      if (fn == null) return;
      textures[maxTextures] = fn;
      System.out.println("Texture " + maxTextures + "(" + fn + ") Added...");
      return;
    }
    if (match(e, props_mi)) {
      Properties();
      return;
    }
    if (match(e, threeD_mi)) {
      showFull3D();
      return;
    }
    if (match(e, frontview_mi)) {
      if (front == null)
        front = new ObjectView("Front View", objects, maxObjects, textures, maxTextures, 1);
      else {
        front.show();
        front.hidden = false;
        updateViews();
      }
      return;
    }
    if (match(e, backview_mi)) {
      if (back == null)
        back = new ObjectView("Back View", objects, maxObjects, textures, maxTextures, 2);
      else {
        back.show();
        back.hidden = false;
        updateViews();
      }
      return;
    }
    if (match(e, topview_mi)) {
      if (top == null)
        top = new ObjectView("Top View", objects, maxObjects, textures, maxTextures, 3);
      else {
        top.show();
        top.hidden = false;
        updateViews();
      }
      return;
    }
    if (match(e, bottomview_mi)) {
      if (bottom == null)
        bottom = new ObjectView("Bottom View", objects, maxObjects, textures, maxTextures, 4);
      else {
        bottom.show();
        bottom.hidden = false;
        updateViews();
      }
      return;
    }
    if (match(e, leftview_mi)) {
      if (left == null)
        left = new ObjectView("Left View", objects, maxObjects, textures, maxTextures, 5);
      else {
        left.show();
        left.hidden = false;
        updateViews();
      }
      return;
    }
    if (match(e, rightview_mi)) {
      if (right == null)
        right = new ObjectView("Right View", objects, maxObjects, textures, maxTextures, 6);
      else {
        right.show();
        right.hidden = false;
        updateViews();
      }
      return;
    }
    if (match(e, sphere_mi)) {
      addSphere();
      return;
    }
    if (match(e, cylinder_mi)) {
      addCylinder();
      return;
    }
    if (match(e, paralelipiped_mi)) {
      addParalelipiped();
      return;
    }
    if (match(e, snowman_mi)) {
      addSphere(0.05, -0.3, 0.0, 0.3);
      addSphere(0.05, 0.06, 0.0, 0.24);
      addSphere(0.05, 0.19, -0.205, 0.01);
      addSphere(0.05, 0.09, -0.237, 0.01);
      addSphere(0.05, 0.0, -0.230, 0.01);
      addSphere(0.05, 0.32, -0.205, 0.018);
      addSphere(0.05, 0.34, 0.0, 0.2);
      addSphere(0.1, 0.4, -0.195, 0.02);
      addSphere(-0.02, 0.393, -0.185, 0.02);
      updateViews();
    }
    super.actionPerformed(e);
  }

  public void updateViews() {
    if (front != null)
      if (!front.hidden) {
        front.maxObjects = maxObjects;
        front.objects = objects;
        front.index = indexView;
        front.busy = busyView;
        front.repaint();
      }
    if (back != null)
      if (!back.hidden) {
        back.maxObjects = maxObjects;
        back.objects = objects;
        back.index = indexView;
        back.busy = busyView;
        back.repaint();
      }
    if (top != null)
      if (!top.hidden) {
        top.maxObjects = maxObjects;
        top.objects = objects;
        top.index = indexView;
        top.busy = busyView;
        top.repaint();
      }
    if (bottom != null)
      if (!bottom.hidden) {
        bottom.maxObjects = maxObjects;
        bottom.objects = objects;
        bottom.index = indexView;
        bottom.busy = busyView;
        bottom.repaint();
      }
    if (left != null)
      if (!left.hidden) {
        left.maxObjects = maxObjects;
        left.objects = objects;
        left.index = indexView;
        left.busy = busyView;
        left.repaint();
      }
    if (right != null)
      if (!right.hidden) {
        right.maxObjects = maxObjects;
        right.objects = objects;
        right.index = indexView;
        right.busy = busyView;
        right.repaint();
      }
  }

  Editor3D(String title) {
    super(title);
    init();
    mb.add(ModelMenu);
    WindowMenu.add(ViewsMenu);
    mb.add(WindowMenu);
    setMenuBar(mb);
  }

  private void init() {
  }

  public void Properties() {
    if (maxObjects >= 0) {
      oi = new ObjectInfo(
          "Show Object Info...", objects, maxObjects, maxTextures);
      oi.setVisible(true);
      oi.setButton.addActionListener(this);
      oi.cancelButton.addActionListener(this);
      oi.names.addItemListener(this);
      indexView = 0;
      busyView = true;
      updateViews();
    } else
      System.out.println("No objects to show.");
  }

  public void showFull3D() {
    Image img1 = null;
    int indx = 0;
    if (_3D == null)
      _3D = new SnowMan();
    else {
      _3D.show();
    }
    _3D.setSize(400, 400);
    _3D.setVisible(true);
    _3D.initialize();
    System.out.println("Loading textures...");
    for (int i = 0; i <= maxTextures; i++) {
      System.out.println(textures[i]);
      File f = new File(textures[i]);
      if (!f.exists()) break;
      img = Toolkit.getDefaultToolkit().getImage(textures[i]);
      _3D.demo.addTexture(img);
    }
    System.out.println("Textures loaded.");
    _3D.start();
    for (int i = 0; i <= maxObjects; i++) {
      indx = objects[i].textureIndex;
      indx = indx + 2;
//  if (indx==0) indx=1;
      switch (objects[i].Type) {
        case 1:
          _3D.addSphere(objects[i].Pos.x,
                        objects[i].Pos.y,
                        objects[i].Pos.z,
                        objects[i].Radius, indx);
          break;
        case 2:
          _3D.addCylinder(objects[i].Pos.x,
                          objects[i].Pos.y,
                          objects[i].Pos.z,
                          objects[i].Radius,
                          objects[i].Height, indx);
          break;
        case 3:
          _3D.addParalelipiped(objects[i].Pos.x,
                               objects[i].Pos.y,
                               objects[i].Pos.z,
                               objects[i].Width,
                               objects[i].Length,
                               objects[i].Height, indx);
          break;
      }
    }
    for (int i = 1; i <= _3D.demo.objects; i++)
      _3D.demo.object[i].mode = 6;
  }

  public void addSphere() {
    String prompts[] = {"x=", "y=", "z=", "R="};
    String defaults[] = {"0.0", "0.0", "0.0", "0.3"};
    DLog = new DoubleLog(this, "Sphere:", prompts, defaults, 6);
    DLog.setVisible(true);
    DLog.setButton.addActionListener(this);
    objectType = 1;
  }

  public void addCylinder() {
    String prompts[] = {"x=", "y=", "z=", "R=", "H="};
    String defaults[] = {"0.0", "0.0", "0.0", "0.3", "0.3"};
    DLog = new DoubleLog(this, "Cylinder:", prompts, defaults, 6);
    DLog.setVisible(true);
    DLog.setButton.addActionListener(this);
    objectType = 2;
  }

  public void addParalelipiped() {
    String prompts[] = {"x=", "y=", "z=", "W=", "L=", "H="};
    String defaults[] = {"0.0", "0.0", "0.0", "0.3", "0.3", "0.3"};
    DLog = new DoubleLog(this, "Paralelipiped::", prompts, defaults, 6);
    DLog.setVisible(true);
    DLog.setButton.addActionListener(this);
    objectType = 3;
  }

  public void addSphere(double _x, double _y, double _z, double R) {
    maxObjects++;
    objects[maxObjects] = new Object3D(maxObjects + "-Sphere", 1);
    objects[maxObjects].Radius = (float) R;
    objects[maxObjects].Pos = new Point3D((float) _x, (float) _y, (float) _z);
    System.out.println("Object " + maxObjects + "-Sphere" + " Added...");
  }

  public void addCylinder(double _x, double _y, double _z, double R, double H) {
    maxObjects++;
    objects[maxObjects] = new Object3D(maxObjects + "-Cylinder", 2);
    objects[maxObjects].Radius = (float) R;
    objects[maxObjects].Height = (float) H;
    objects[maxObjects].Pos = new Point3D((float) _x, (float) (_y - (float) (H / 2d)), (float) _z);
    System.out.println("Object " + maxObjects + "-Cylinder" + " Added...");
  }

  public void addParalelipiped(double _x, double _y, double _z, double W, double L, double H) {
    maxObjects++;
    objects[maxObjects] = new Object3D(maxObjects + "-Paralelipiped", 3);
    objects[maxObjects].Width = (float) W;
    objects[maxObjects].Height = (float) H;
    objects[maxObjects].Length = (float) L;
    objects[maxObjects].Pos = new Point3D((float) _x, (float) _y, (float) _z);
    System.out.println("Object " + maxObjects + "-Paralelipiped" + " Added...");
  }

  public static void main(String args[]) {
    Editor3D mL = new Editor3D(
        "Editor3D");
    mL.setSize(150, 150);
    mL.setVisible(true);
  }
}