package ToyIP;

import ToyIP.*;

import java.io.*;
import java.awt.*;
import java.util.*;
import javax.swing.*;

import vtk.util.VtkColors;
import vtk.util.VtkPanelUtil;
import vtk.util.VtkPanelContainer;
import vtk.*;


public class AppletRenderer extends JComponent implements VtkPanelContainer {

  private vtkPanel renWin;

  public vtkActor generateBase() {
    // Define the base that the cube sits on.  Create its associated mapper
    // and actor.  Set the position of the actor.
    vtkCubeSource baseModel = new vtkCubeSource();
    baseModel.SetXLength(1.5);
    baseModel.SetYLength(.01);
    baseModel.SetZLength(1.5);
    vtkPolyDataMapper baseMapper = new vtkPolyDataMapper();
    baseMapper.SetInput(baseModel.GetOutput());
    vtkActor base = new vtkActor();
    base.SetMapper(baseMapper);
    base.SetPosition(.5, -0.09, .5);
    return base;
  }

  public vtkActor generatePolyhedron(java.util.List< Double[] > planes) {
    vtkPoints points = new vtkPoints();
    for (int x = 0; x < 10; x++)
      for (int y = 0; y < 10; y++)
        for (int z = 0; z < 10; z++) {
          boolean add = true;
          for (Double p[] : planes)
            if (p[0] * x + p[1] * y + p[2] * z > p[3])
              add = false;
          if (add) points.InsertNextPoint(x, y, z);
        }
    vtkPolyData origin = new vtkPolyData();
    origin.SetPoints(points);
    vtkHull polyhedron = new vtkHull();
    polyhedron.SetInput(origin);
    for (Double p[] : planes) {
      System.out.print("Rendering a constraint ");
      System.out.print(p[0].toString() + "x + ");
      System.out.print(p[1].toString() + "y + ");
      System.out.print(p[2].toString() + "z <= ");
      System.out.println(p[3].toString());
      polyhedron.AddPlane(p[0], p[1], p[2], p[3]);
    }
    vtkPolyDataMapper polyMapper = new vtkPolyDataMapper();
    polyMapper.SetInput(polyhedron.GetOutput());
    vtkActor poly = new vtkActor();
    poly.SetMapper(polyMapper);
    poly.SetPosition(0, 0, 0);
    poly.GetProperty().SetDiffuseColor(VtkColors.BANNANA);
    poly.GetProperty().SetOpacity(.6);
    return poly;
  }

  public vtkActor generateIntegers(java.util.List< Double[] > planes) {
    vtkPoints points = new vtkPoints();
    for (Integer x = 0; x < 10; x++)
      for (Integer y = 0; y < 10; y++)
        for (Integer z = 0; z < 10; z++) {
          boolean add = false;
          for (Double p[] : planes)
            if (p[0] * x + p[1] * y + p[2] * z <= p[3])
              add = true;
          if (add) {
            points.InsertNextPoint(x, y, z);
            System.out.println("Adding point [" + x.toString() + ", " + y.toString() + ", " + z.toString() + "]");
          }
        }

    vtkUnstructuredGrid grid = new vtkUnstructuredGrid();
    grid.Allocate(1, 1);
    grid.SetPoints(points);

    // Create a sphere to use as a glyph source for vtkGlyph3D.
    vtkSphereSource sphere = new vtkSphereSource();
    sphere.SetRadius(0.04);
    sphere.SetPhiResolution(10);
    sphere.SetThetaResolution(10);
    // vtkSelectVisiblePoints visFilter = new vtkSelectVisiblePoints();
    // visFilter.SetInput(grid);
    vtkPolyData pointsData = new vtkPolyData();
    pointsData.SetPoints(points);

    vtkGlyph3D vertices = new vtkGlyph3D();
    vertices.SetInput(pointsData);
    vertices.SetSource(sphere.GetOutput());
    // Create a mapper and actor to display the glyphs.
    vtkPolyDataMapper sphereMapper = new vtkPolyDataMapper();
    sphereMapper.SetInput(vertices.GetOutput());
    sphereMapper.ScalarVisibilityOff();
    vtkActor cubeVertices = new vtkActor();
    cubeVertices.SetMapper(sphereMapper);
    cubeVertices.GetProperty().SetDiffuseColor(VtkColors.RED);
    cubeVertices.GetProperty().SetOpacity(1);
    return cubeVertices;
  }

  public void updatePolyhedron(java.util.List< Double[] > planes) {
    vtkRenderer ren = renWin.GetRenderer();
    // ren.AddActor(generatePolyhedron(planes));
    // ren.AddActor(generateIntegers(planes));
  }


  public vtkActor generateLabel() {
    // Define the text for the label
    vtkVectorText caseLabel = new vtkVectorText();
    caseLabel.SetText("Toy Integer Programming Solver");
    // Set up a transform to move the label to a new position.
    vtkTransform aLabelTransform = new vtkTransform();
    aLabelTransform.Identity();
    aLabelTransform.Translate(-0.2, 0, 1.25);
    aLabelTransform.Scale(.05, .05, .05);
    // Move the label to a new position.
    vtkTransformPolyDataFilter labelTransform = new vtkTransformPolyDataFilter();
    labelTransform.SetTransform(aLabelTransform);
    labelTransform.SetInput(caseLabel.GetOutput());
    // Create a mapper and actor to display the text.
    vtkPolyDataMapper labelMapper = new vtkPolyDataMapper();
    labelMapper.SetInput(labelTransform.GetOutput());
    vtkActor label = new vtkActor();
    label.SetMapper(labelMapper);
    return label;
  }

  public AppletRenderer() {
    // Setup VTK rendering panel
    renWin = new vtkPanel();
    VtkPanelUtil.setSize(renWin, 500, 500);

    // Create the Renderer, RenderWindow, and RenderWindowInteractor
    vtkRenderer ren = renWin.GetRenderer();

    // Add the actors to the renderer
    ren.AddActor(generateBase());
    ren.AddActor(generateLabel());

    // Set the background color.
    ren.SetBackground(VtkColors.SLATE_GREY);

    // Position the camera.
    ren.GetActiveCamera().Dolly(1.2);
    ren.GetActiveCamera().Azimuth(30);
    ren.GetActiveCamera().Elevation(20);
    ren.ResetCameraClippingRange();

    // Place renWin in the center of this panel
    setLayout(new BorderLayout());
    add(renWin, BorderLayout.CENTER);
  }

  public vtkPanel getRenWin() {
    return renWin;
  }

}
