/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on 2005/10/19, 21:16
!  AUTHOR(S): KOGA, Junichiro
!  File : LeftClickAction.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */

package ciss.phase_viewer.acviewer.mouselistener;

import java.awt.event.MouseEvent;
import java.util.Vector;

import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Shape3D;
import javax.vecmath.Point2d;
import javax.vecmath.Point3d;

import org.apache.log4j.Logger;

import ciss.phase_viewer.acviewer.MainPanel;
import ciss.phase_viewer.acviewer.scenegraphelements.TGAtom;
import ciss.phase_viewer.acviewer.scenegraphelements.atom.AtomFilledCircle;
import ciss.phase_viewer.acviewer.scenegraphelements.atom.AtomObject;
import ciss.phase_viewer.acviewer.scenegraphelements.atom.AtomSphere;

import com.sun.j3d.utils.geometry.Primitive;
import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.picking.PickTool;

/**
 * 
 */
public class LeftClickAction extends MouseMotionListenerAction {
    private Logger logger = Logger.getLogger(LeftClickAction.class.getName());

    private boolean dragCalled = false;

    private PickCanvas pickTool;

    /** Creates a new instance of LeftClickAction */
    public LeftClickAction(MainPanel parent) {
        super(parent);
        pickTool = new PickCanvas(parent.getCanvas(), parent.getRootBranch());
        pickTool.setMode(PickTool.BOUNDS);
    }

    void finalize(MouseEvent e) {
        if (!dragCalled) {
            return;
        }
        int resolution = parent.getScene().getCD().getNumAt();
        if (resolution < 100)
            resolution = 100;
        Point3d finalPoint = getCoordsFromMousePos(parent, e);
        initPoint.z = 10.d;
        finalPoint.z = -10.d;

        Point3d finalMousePos = new Point3d(e.getX(), e.getY(), -10);

        boolean inismallx = true;
        int startx = (int) initMousePos.x;
        int endx = (int) finalMousePos.x;
        if (startx > endx) {
            startx = (int) finalMousePos.x;
            endx = (int) initMousePos.x;
            inismallx = false;
        }
        int increx = (int) Math.round((double) (endx - startx) / resolution);

        boolean inismally = true;
        int starty = (int) initMousePos.y;
        int endy = (int) finalMousePos.y;
        if (starty > endy) {
            starty = (int) finalMousePos.y;
            endy = (int) initMousePos.y;
        }
        int increy = (int) Math.round((double) (endy - starty) / resolution);

        if (increx <= 0)
            increx = 1;
        if (increy <= 0)
            increy = 1;

        Vector vec = new Vector();
        for (int ix = startx; ix < endx; ix = ix + increx) {
            for (int jy = starty; jy < endy; jy = jy + increy) {
                int x = ix;
                int y = jy;
                pickTool.setShapeLocation(x, y);
                PickResult[] result = pickTool.pickAll();
                if (result != null) {
                    for (int i = 0; i < result.length; i++) {
                        Primitive pri = (Primitive) result[i]
                                .getNode(PickResult.PRIMITIVE);
                        if (pri != null && pri instanceof AtomSphere) {
                            AtomObject obj = ((AtomSphere) pri).getAtomObject();
                            if (vec.indexOf(obj) < 0)
                                vec.add(obj);
                        }
                        Shape3D s3d = (Shape3D) result[i]
                                .getNode(PickResult.SHAPE3D);
                        if (s3d != null && s3d instanceof AtomFilledCircle) {
                            AtomObject obj = ((AtomFilledCircle) s3d)
                                    .getAtomObject();
                            if (vec.indexOf(obj) < 0)
                                vec.add(obj);
                        }
                    }
                }
            }
        }

        ((TGAtom) parent.getScene().getTGAtom()).stopMeasure();
        int nselec = 0;
        int nnselec = 0;
        for (int i = 0; i < vec.size(); i++) {
            boolean b = ((AtomObject) vec.get(i)).toggleSelected();
            if (b)
                nselec += 1;
            else
                nnselec += 1;
        }
        if (nselec > 0)
            logger.info("selected " + nselec + " atoms ");
        if (nnselec > 0)
            logger.info("deselected " + nnselec + " atoms ");

        ((TGAtom) parent.getScene().getTGAtom()).restartMeasure();

        parent.finalizeRectangle();
        // BoundingBox box = new BoundingBox(initMousePos, finalMousePos);
        // pickTool.setShape(new PickBounds(box), new Point3d());
        // pickTool.setShapeLocation((int)initMousePos.x,(int)initMousePos.y);
        // PickResult[] result = pickTool.pickAllSorted();
        // if (result != null) {
        // for (int i = 0; i < result.length; i++) {
        // Primitive pri = (Primitive) result[i]
        // .getNode(PickResult.PRIMITIVE);
        // if (pri != null && pri instanceof AtomSphere) {
        // AtomObject obj = ((AtomSphere) pri).getAtomObject();
        // obj.setSelected();
        // logger.debug(obj);
        // }
        // Shape3D s3d = (Shape3D) result[i].getNode(PickResult.SHAPE3D);
        // if (s3d != null && s3d instanceof AtomFilledCircle) {
        // AtomObject obj = ((AtomFilledCircle) s3d).getAtomObject();
        // obj.setSelected();
        // logger.debug(obj);
        // }
        // }
        //
        // } else {
        // logger.debug("nothing picked....");
        // }
        //
        // BoundingBox bounds = new BoundingBox(initPoint, finalPoint);
        // logger.debug("bounds: " + bounds);
        // TransformGroup tg = parent.getScene().getTGAtom();
        // boolean regedNullMeasure = false;
        // AtomObject[] aobjs = ((TGAtom) tg).getAtomObjects();
        // if (aobjs != null) {
        // for (int i = 0; i < aobjs.length; i++) {
        // AtomObject aobj = aobjs[i];
        // BoundingSphere abound = aobj.getTransformedBounds();
        // if (check(initPoint, finalPoint, abound)) {
        // if (!regedNullMeasure) {
        // ((TGAtom) parent.getScene().getTGAtom())
        // .registerMeasure(new NullMeasure(
        // (Measurable) parent.getScene()
        // .getTGAtom()));
        // regedNullMeasure = true;
        // }
        // logger.debug("caught atom: " + aobj);
        // aobj.toggleSelected();
        // }
        // }
        // }
        // for ( int i=0 ; i<tg.numChildren() ; i++ ) {
        // Object object = tg.getChild(i);
        // if ( object instanceof AtomObjectBG ) {
        // AtomObject aobj = ((AtomObjectBG) object).getAssociatedAtomObject();
        // BoundingSphere abound = aobj.getTransformedBounds();
        // // logger.debug("atom bounds: "+abound);
        // if ( check(initPoint,finalPoint,abound) ) {
        // if ( !regedNullMeasure ) {
        // ((TGAtom) parent.getScene().getTGAtom()).
        // registerMeasure(new NullMeasure((Measurable)
        // parent.getScene().getTGAtom()));
        // regedNullMeasure = true;
        // }
        // logger.debug("caught atom: "+aobj);
        // aobj.toggleSelected();
        // }
        // }
        // }
        initx = 0.f;
        inity = 0.f;
        ((TGAtom) parent.getScene().getTGAtom()).setRotationEnabled(true);
        dragCalled = false;
    }

    private boolean check(Point3d point1, Point3d point2, BoundingSphere sphere) {

        double x1 = point1.x;
        double y1 = point1.y;

        double x2 = point2.x;
        double y2 = point2.y;

        if (x1 > x2) {
            double tmp = 0.d;
            tmp = x1;
            x1 = x2;
            x2 = tmp;
        }

        if (y1 > y2) {
            double tmp = 0.d;
            tmp = y1;
            y1 = y2;
            y2 = tmp;
        }

        Point3d center = new Point3d();
        Point2d p2d = new Point2d();
        parent.getCanvas().getPixelLocationFromImagePlate(center, p2d);
        sphere.getCenter(center);
        double radius = sphere.getRadius();
        radius = 0;
        double x3 = center.x - radius;
        double y3 = -center.y - radius;

        double x4 = center.x + radius;
        double y4 = -center.y + radius;

        return x1 < x4 && x3 < x2 && y1 < y4 && y3 < y2;
    }

    private float initx;

    private float inity;

    private Point3d initPoint;

    private Point3d initMousePos;

    void init(MouseEvent e) {
        initMousePos = new Point3d(e.getX(), e.getY(), 10);
        initPoint = getCoordsFromMousePosPlat(parent, e);
        initx = (float) initPoint.x;
        inity = -(float) initPoint.y;
        parent.initializeRectangle(initx, inity);
    }

    void processMouseDrag(MouseEvent e) {
        ((TGAtom) parent.getScene().getTGAtom()).setRotationEnabled(false);
        Point3d point = getCoordsFromMousePosPlat(parent, e);
        float floatx = (float) point.x - initx;
        float floaty = -(float) point.y - inity;
        parent.updateRectangle(floatx, floaty);
        logger.debug("coordinate: " + point.x + ", " + point.y);
        dragCalled = true;
    }

    void processMouseMove(MouseEvent e) {
    }

}
