package etomica.lattice.crystal;
import etomica.api.IVector;
import etomica.math.geometry.Polytope;
import etomica.space.ISpace;
import etomica.space3d.Space3D;

/**
 * Primitive group for a hexagonal system.  Primitive-vector angles
 * are (90,90,120) degrees and two vectors are of equal length.
 */
public class PrimitiveHexagonal extends Primitive {
    
    private static final long serialVersionUID = 1L;
    protected double ab;
    protected static final double gamma = etomica.units.Degree.UNIT.toSim(120.);
    protected static final double cosGamma = Math.cos(gamma);
    protected static final double sinGamma = Math.sin(gamma);
    
    public PrimitiveHexagonal(ISpace space) {
        this(space, 1.0, 1.0);
    }
    public PrimitiveHexagonal(ISpace space, double ab, double c) {
        super(space);
        setSize(new double[]{ab, ab, c});
        this.ab = ab;
        setAngles(new double[]{rightAngle, rightAngle, gamma});
    }
    
    //called by superclass constructor
    public Primitive makeReciprocal() {
//        return PrimitiveHexagonalReciprocal(space, 2.0*Math.PI/(ab*sinGamma),
//                2.0*Math.PI/(ab*sinGamma), 2.0*Math.PI/size[2], 2.0*Math.PI/(size[2]*Math.sin(angle[1])), angle[1]);
        return new PrimitiveHexagonalReciprocal(space, 2.0 * Math.PI * ab / sinGamma, 2.0 * Math.PI * size[2]);
    }
    
    public void setSizeAB(double newAB) {
        if (newAB == ab) {
            return;
        }
        setSize(new double[]{newAB, newAB, size[2]});
        ab = newAB;
    }
    
    public double getSizeAB() {
        return ab;
    }
    
    public void setSizeC(double newC) {
        if (newC == size[2]) {
            return;
        }
        setSize(new double[]{ab, ab, newC});
    }
    public double getSizeC() {return size[2];}

    public double getAngleAlpha() {
        return angle[0];
    }

    public double getAngleBeta() {
        return angle[1];
    }

    public double getAngleGamma() {
        return angle[2];
    }

    protected void update() {
        latticeVectors[0].setX(0,size[0]);
        latticeVectors[1].setX(0,size[0]*cosGamma);
        latticeVectors[1].setX(1,size[0]*sinGamma);
        latticeVectors[2].setX(2,size[2]);
    }
    
    /**
     * Returns a new PrimitiveHexagonal with the same size as this one.
     */
    public Primitive copy() {
        return new PrimitiveHexagonal(space, ab, size[2]);
    }
    
    public void scaleSize(double scale) {
        setSize(new double[]{scale*ab, scale*ab, scale*size[2]});
        ab = ab * scale;
    }

    public int[] latticeIndex(IVector q) {
        throw new RuntimeException("latticeIndex method not implemented yet in primitive");
   /*     for(int i=0; i<D; i++) {
            double x = q.x(i)/size;
            idx[i] = (x < 0) ? (int)x - 1 : (int)x; //we want idx to be the floor of x
        }
        return idx;
   */ }
    
    public int[] latticeIndex(IVector q, int[] dimensions) {
        throw new RuntimeException("latticeIndex method not implemented yet in primitive");
   /*     for(int i=0; i<D; i++) {
            double x = q.x(i)/size;
            idx[i] = (x < 0) ? (int)x - 1 : (int)x; //we want idx to be the floor of x
            while(idx[i] >= dimensions[i]) idx[i] -= dimensions[i];
            while(idx[i] < 0)              idx[i] += dimensions[i];
        }
        return idx;
    */}
    
    public Polytope wignerSeitzCell() {
        throw new RuntimeException("method wignerSeitzCell not yet implemented");
    }
    
    public String toString() {return "Hexagonal";}
    
    protected static class PrimitiveHexagonalReciprocal extends PrimitiveHexagonal {
        public PrimitiveHexagonalReciprocal(ISpace space, double ab, double c) {
            super(space, ab, c);
        }

        protected void update() {
            latticeVectors[0].setX(0, ab*sinGamma);
            latticeVectors[0].setX(1,-ab*cosGamma);
            latticeVectors[1].setX(1, ab);
            latticeVectors[2].setX(2, size[2]);
        }
        
        private static final long serialVersionUID = 1L;
    }

    public static void main(String args[]) {
        PrimitiveHexagonal primitive = new PrimitiveHexagonal(Space3D.getInstance(), 1, 1);
        IVector[] v = primitive.vectors();
        Primitive reciprocal = primitive.makeReciprocal();
        IVector[] vr = reciprocal.vectors();
        for (int i=0; i<v.length; i++) {
            for (int j=0; j<vr.length; j++) {
                System.out.println(i+" "+j+" "+v[i].dot(vr[j]));
            }
        }
    }
}
    

@@ -1302,14 +1302,15 @@
 .PI 
-* ab /
+/ (ab *
  sin
@@ -1314,16 +1314,17 @@
 sinGamma
+)
 , 2.0 * 
@@ -1331,17 +1331,17 @@
 Math.PI 
-*
+/
  size%5B2%5D
@@ -4233,12 +4233,12 @@
 (), 
-1, 1
+2, 2
 );%0A 
@@ -4375,32 +4375,138 @@
 ocal.vectors();%0A
+        for (int j=0; j%3Cvr.length; j++) %7B%0A            System.out.println(j+%22 %22+v%5Bj%5D+%22 %22+vr%5Bj%5D);%0A        %7D%0A
         for (int

reciprocal magnitude should be inversely proportional to real-space magnitude