# -*- coding: utf-8 -*-
"""
Galactic coordinates for map generation etc.
Location is a tuple (r, angle). From that, we can calculate what quadrant
and sector and field etc!

Created on Sat Jul  8 03:38:57 2017

@author: mjm
"""
import numpy as np
import logging
import logging.config

class Location(object):
    def __init__(self,rho,phi):
        self._rho = rho
        self._phi = phi % 1.0
    
    def polar(self):
        return (self._rho, self._phi)

    def cart(self):
        x = self._rho*np.cos(2*np.pi*self._phi)
        y = self._rho*np.sin(2*np.pi*self._phi)
        return (x,y)
        
    def quadrant(self):
        bins = [0.00,0.25,0.50,0.75]
        return int(np.digitize(self._phi,bins))
    
    def sector(self):
        bins = [0.00,0.25,0.50,0.75]
        return int(np.digitize((self._phi % 0.25)/0.25,bins))
        
    def field(self):
        bins = [0.00,0.50,0.75,1.00,1.50]
        return int(np.digitize(self._rho,bins))
        
    def qsf(self):
        return (self.quadrant(),self.sector(),self.field())
    
    def plot(self):
        from matplotlib import pyplot as plt
        ax = plt.subplot(111, projection='polar')
        ax.set_theta_offset(0.5*np.pi)
        ax.set_theta_direction(-1)
        ax.plot(2*np.pi*self._phi, self._rho, 'go')
        ax.set_rmax(2)
        ax.set_rticks([0.00,0.50,0.75,1.00,1.50])  # less radial ticks
        ax.set_xticks(2*np.pi*np.linspace(0,  1, 16, endpoint=False))
        ax.set_rlabel_position(-22.5)  # get radial labels away from plotted line
        ax.grid(True)
        
def dist(loc1,loc2):
    x1,y1 = loc1.cart()
    x2,y2 = loc2.cart()
    ans = np.sqrt((x1-x2)**2+(y1-y2)**2)
    return ans
    
def qsf2str_tup(qsf, formatting='short'):
    """
    Quadrants A B C D
    Sectors 1 2 3 4
    Fields Core Inner Shell Mantle Outer
    """
    pass
    if formatting == 'short':
        lookup = {"quadrant": {1:'A',2:'B',3:'C',4:'D'},
            "sector": {1: '1', 2: '2', 3: '3', 4: '4'},
            "field": {1: 'C', 2: 'I', 3: 'M', 4: 'S', 5: 'O'}}
    elif formatting == 'long':
        lookup = {"quadrant": {1:'A',2:'B',3:'C',4:'D'},
            "sector": {1: '1', 2: '2', 3: '3', 4: '4'},
            "field": {1: 'Core', 2: 'Inner', 3: 'Mantle', 4: 'Shell', 5: 'Outer'}}
    elif formatting == 'QxSxFx':
        lookup = {"quadrant": {1:'QA',2:'QB',3:'QC',4:'QD'},
            "sector": {1: 'S1', 2: 'S2', 3: 'S3', 4: 'S4'},
            "field": {1: 'FC', 2: 'FI', 3: 'FM', 4: 'FS', 5: 'FO'}}
    elif formatting == 'QnSnFn':
        lookup = {"quadrant": {1:'Q1',2:'Q2',3:'Q3',4:'Q4'},
            "sector": {1: 'S1', 2: 'S2', 3: 'S3', 4: 'S4'},
            "field": {1: 'F1', 2: 'F2', 3: 'F3', 4: 'F4', 5: 'F0'}}
    elif formatting == 'extra':
        lookup = {"quadrant": {1:'Quadrant A',2:'Quadrant B',3:'Quadrant C',4:'Quadrant D'},
            "sector": {1: 'Sector 1', 2: 'Sector 2', 3: 'Sector 3', 4: 'Sector 4'},
            "field": {1: 'Core', 2: 'Inner field', 3: 'Mantle', 4: 'Shell', 5: 'Outer field'}}
    else:
        raise Exception #unrecognised formatting
    ans = (lookup['quadrant'][qsf[0]],lookup['sector'][qsf[1]],lookup['field'][qsf[2]])
    return ans

def qsf2str(qsf, formatting='short', order = 'qsf'):
    str_tup = qsf2str_tup(qsf,formatting)
    if order == 'qsf':
        ans = str_tup[0] + ", " + str_tup[1] + ", in the " + str_tup[2]
    elif order == 'qfs':
        ans = str_tup[0] + " in the " + str_tup[2] + ", in " + str_tup[1]
    elif order == 'sqf':
        ans = str_tup[1] + " of " + str_tup[0] + ", in the " + str_tup[2]
    elif order == 'sfq':
        ans = str_tup[1] + " in the " + str_tup[2] + ", in " + str_tup[0]
    elif order == 'fqs':
        ans = str_tup[2] + " of " + str_tup[0] + ", in " + str_tup[1]
    elif order == 'fsq':
        ans = str_tup[2] + " of " + str_tup[1] + ", in " + str_tup[0]
    else:
        raise Exception #unrecognised formatting
    return ans
        
def test_module():
    loc1 = Location(0.6,0.78) # should be B1I
    loc1.plot()
    print qsf2str(loc1.qsf(), formatting='extra', order='sqf')
    loc2 = Location(0.3,0.2) # should be B1I
    loc2.plot()
    print qsf2str(loc2.qsf(), formatting='extra', order='sqf')
    print dist(loc1,loc2)
    
if __name__ == "__main__":
    logging.config.fileConfig('logs.conf')
    logging.info("Testing location module started.")  
    test_module()
    logging.info("Testing location module finished.")
