/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package skyview.survey;

import skyview.geometry.projecter.Interleave;

/**
 *
 * @author tmcglynn
 */
public class HPXCvt {
    long nside;
    long npix;
    long ntile;
    long ncap;
    long order;
    long[] jpll = { 1,3,5,7,0,2,4,6,1,3,5,7 };
    Interleave weaver;
    
    
    public HPXCvt(long order) {
        nside      = 1<<order;
        this.order = order;
        ntile      = npix*npix;
        npix       = 12*ntile; 
        ncap       = 2*(ntile-nside);
        if (order <= 15) {
            weaver = new Interleave((int)order);
        } else {
            weaver = new Interleave(15);
        }
    }
    
    long isqrt(long l) {
        return (long) Math.sqrt(l);
    }
    
    public long ring2nest(long pix) {
        long nl2 = 2*nside;

        long iring, iphi, face_num;
        long kshift = 0;
        long nr;
        if (pix<ncap){ // North Polar cap
            iring = (1 + isqrt(1+2*pix) ) >>1; //counted from North pole
            iphi  = (pix+1) - 2*iring*(iring-1);
            kshift = 0;
            nr = iring;
            face_num=special(iphi-1,nr);
            
        } else if ( pix < (npix - ncap))  { // Equatorial region
            long ip  = pix - ncap;
            long tmp = (order >= 0) ? ip>>(order + 2) : ip/(4*nside);
            iring  = tmp + nside;
            iphi   = ip - tmp*4*nside + 1;
            kshift = (iring+nside)&1;
            nr = nside;
            long ire = tmp + 1;
            long irm = nl2 + 1 - tmp;
            long ifm = iphi - (ire>>1) + nside - 1;
            long ifp = iphi - (irm>>1) + nside -1;
            if (order >= 0) {
                ifm >>= order; 
                ifp >>= order; 
            } else {
                ifm /= nside; 
                ifp /= nside; 
            }
            face_num = (ifp==ifm) ? (ifp|4) : ((ifp<ifm) ? ifp : (ifm+8));
        } else { // South Polar cap
            long ip = npix - pix;
            iring = (1+isqrt(2*ip-1)) >> 1; //counted from South pole
            iphi  = 4*iring + 1 - (ip - 2*iring*(iring-1));
            kshift = 0;
            nr = iring;
            System.out.println("NR="+nr+" "+nl2+" "+iring+" "+iphi);
            iring = 2*nl2 - iring;
            face_num = special(iphi-1,nr) + 8;
        }
        
        

        long irt = iring - ((2+(face_num>>2))*nside) + 1;
        long ipt = 2*iphi- jpll[(int)face_num]*nr - kshift -1;
        if (ipt >= nl2) {
            ipt -= 8*nside;
        }

        long ix =  (ipt-irt) >>1;
        long iy = (-ipt-irt) >>1;
        
        return pix(face_num, ix, iy);
    }
    
    long special(long a, long b) {
        long bs = b<<1;
        long t = 0;
        if (a > bs) {
            t = 1;
        }
        a -= t*bs;
        long u = 0;
        if (a >= b) {
            u = 1;
        }
        return t<<1 + u;        
    }
    
    long pix(long face, long ix, long iy) {
        return face*ntile + weaver.pixel((int)ix, (int)iy);
    }
    
    public static void main(String[] args) {
        
        long order = Integer.parseInt(args[0]);
        long start = Long.parseLong(args[1]);
        long result = new HPXCvt(order).ring2nest(start);
        System.out.println("Order:"+order);
        System.out.println("   "+start+" => "+result);
    }
}
