package org.helioviewer.jhv.base.scale;

import org.helioviewer.jhv.base.astronomy.Position;
import org.helioviewer.jhv.base.astronomy.Sun;
import org.helioviewer.jhv.base.math.MathUtils;
import org.helioviewer.jhv.base.math.Vec2;
import org.helioviewer.jhv.base.math.Vec3;
import org.helioviewer.jhv.layers.Layers;

public interface Transform {

    public Vec2 transform(Vec3 pt, GridScale scale);

    public Vec3 transformInverse(Vec2 pt, GridScale scale);

    public static Transform transformpolar = new TransformPolar();
    public static Transform transformlatitudinal = new TransformLatitudinal();

    public static class TransformPolar implements Transform {
        @Override
        public Vec2 transform(Vec3 pt, GridScale scale) {
            double r = Math.sqrt(pt.x * pt.x + pt.y * pt.y);
            double theta = Math.atan2(-pt.x, -pt.y);
            theta += 2 * Math.PI;
            theta %= 2 * Math.PI;
            double scaledr = scale.getYValueInv(r);
            double scaledtheta = scale.getXValueInv(theta * MathUtils.radeg);
            return new Vec2(scaledtheta, scaledr);
        }

        @Override
        public Vec3 transformInverse(Vec2 pt, GridScale scale) {
            double r = pt.x;
            double theta = pt.y / MathUtils.radeg;
            //TBD
            return new Vec3();
        }

    }

    public static class TransformLatitudinal implements Transform {
        @Override
        public Vec2 transform(Vec3 pt, GridScale scale) {
            double theta = Math.PI / 2 - Math.acos(-pt.y);
            double phi = Math.atan2(pt.x, pt.z);
            Position.L p = Sun.getEarth(Layers.getLastUpdatedTimestamp());
            phi -= Math.PI + p.lon;
            phi += 6 * Math.PI;
            phi %= 2 * Math.PI;
            double scaledphi = scale.getXValueInv(phi * MathUtils.radeg);
            double scaledtheta = scale.getYValueInv(theta * MathUtils.radeg);
            return new Vec2(scaledphi, scaledtheta);
        }

        @Override
        public Vec3 transformInverse(Vec2 pt, GridScale scale) {
            double phi = pt.x / MathUtils.radeg;
            double theta = pt.y / MathUtils.radeg;
            phi += Math.PI;
            theta = -theta + Math.PI / 2;
            return new Vec3(Math.sin(theta) * Math.sin(phi), Math.cos(theta), Math.sin(theta) * Math.cos(phi));
        }
    }

}

@@ -181,16 +181,59 @@
 hUtils;%0A
+import org.helioviewer.jhv.base.math.Quat;%0A
 import o
@@ -267,16 +267,16 @@
 h.Vec2;%0A
-
 import o
@@ -775,32 +775,192 @@
 dScale scale) %7B%0A
+            Position.L p = Sun.getEarth(Layers.getLastUpdatedTimestamp());%0A            Quat q = new Quat(p.lat, 0);%0A            pt = q.rotateInverseVector(pt);%0A
             doub
@@ -1426,17 +1426,17 @@
  r = pt.
-x
+y
 ;%0A      
@@ -1448,36 +1448,37 @@
  double theta = 
+-
 pt.
-y
+x
  / MathUtils.rad
@@ -1497,33 +1497,298 @@
     
-//TBD%0A            return 
+double y = r * Math.cos(theta);%0A            double x = r * Math.sin(theta);%0A            double z = Math.sqrt(1 - x * x - y * y);%0A            Position.L p = Sun.getEarth(Layers.getLastUpdatedTimestamp());%0A            Quat q = new Quat(p.lat, p.lon);%0A            return q.rotateInverseVector(
 new 
@@ -1792,16 +1792,24 @@
 ew Vec3(
+x, y, z)
 );%0A     
@@ -1809,25 +1809,24 @@
 ;%0A        %7D%0A
-%0A
     %7D%0A%0A    p

fix polar annotations