import os
import sys
import Tigger
import numpy
import tempfile
import json
import codecs
import shlex
import shutil
import glob
import subprocess

from astLib.astWCS import WCS
from astropy.io.votable import parse_single_table
from Tigger.Models import SkyModel, ModelClasses


CONFIG = os.environ["CONFIG"]
INPUT = os.environ["INPUT"]
MSDIR = os.environ["MSDIR"]
OUTPUT = os.environ["OUTPUT"]

with codecs.open(CONFIG, "r", "utf8") as stdr:
    cab = json.load(stdr)

junk = cab["junk"]
args = []
msname = None

sofia_file = 'sofia_parameters.par'
wstd = open(sofia_file, 'w')

wstd.write('output.directory={:s}\n'.format(OUTPUT))
port2tigger = False
image = None

for param in cab['parameters']:
    name = param['name']
    value = param['value']
    dtype = param['dtype']

    # Fix the sofia issue of needing lowercase booleans.
    if dtype == 'bool':
        if (value == True) and (not name == 'port2tigger'):
            value = 'true'
        elif (not name == 'port2tigger'):
            value = 'false'

    if dtype == 'list:str' and value is not None:
        try:
            value = ",".join(map(str, value))  # Flatten the list into a string
        except ValueError:
            pass
    
    if value is None:
        continue
    if name == "port2tigger":
        port2tigger = value
        continue
    if name == "output.writeCatXML":
        writecat = value
    if name == "parameter.enable":
        parameterise = value
    if name == "input.data":
        image = value

    wstd.write('{0}={1}\n'.format(name, value))

wstd.close()

_runc = " ".join([cab['binary'], sofia_file])

try:
    subprocess.check_call(shlex.split(_runc))
finally:
    for item in junk:
        for dest in [OUTPUT, MSDIR]: # these are the only writable volumes in the container
            items = glob.glob("{dest}/{item}".format(**locals()))
            for f in items:
                if os.path.isfile(f):
                    os.remove(f)
                elif os.path.isdir(f):
                    shutil.rmtree(f)
                # Leave other types

if not port2tigger:
    sys.exit(0)

# convert to data file to Tigger LSM
# First make dummy tigger model
tfile = tempfile.NamedTemporaryFile(suffix='.txt')
tfile.flush()

if image and writecat and parameterise:
    pass
else:
    sys.exit(0)

prefix = os.path.splitext(image)[0]
tname_lsm = prefix + ".lsm.html"
with open(tfile.name, "w") as stdw:
    stdw.write("#format:name ra_d dec_d i emaj_s emin_s pa_d\n")

model = Tigger.load(tfile.name)
tfile.close()


def tigger_src(src, idx):

    name = "SRC%d" % idx
    flux = ModelClasses.Polarization(src["f_sum"], 0, 0, 0)
    ra = numpy.deg2rad(src["ra"])
    dec = numpy.deg2rad(src["dec"])
    pos = ModelClasses.Position(ra, dec)
    ex = numpy.deg2rad(src["ell_maj"])
    ey = numpy.deg2rad(src["ell_min"])
    pa = numpy.deg2rad(src["ell_pa"])
    print(name)

    if ex and ey:
        shape = ModelClasses.Gaussian(ex, ey, pa)
    else:
        shape = None
    source = SkyModel.Source(name, pos, flux, shape=shape)
    # Adding source peak flux (error) as extra flux attributes for sources,
    # and to avoid null values for point sources I_peak = src["Total_flux"]
    if shape:
        source.setAttribute("I_peak", float(src["f_max"]))
    else:
        source.setAttribute("I_peak", float(src["f_sum"]))

    return source

table = parse_single_table('{0}_cat.xml'.format(prefix))
data = table.array

for i, src in enumerate(data):
    model.sources.append(tigger_src(src, i))

wcs = WCS(image)
centre = wcs.getCentreWCSCoords()
model.ra0, model.dec0 = map(numpy.deg2rad, centre)

model.save(tname_lsm)
# Rename using CORPAT
_runc = "tigger-convert %s --rename -f" % tname_lsm
try:
    subprocess.check_call(shlex.split(_runc))
finally:
    for item in junk:
        for dest in [OUTPUT, MSDIR]: # these are the only writable volumes in the container
            items = glob.glob("{dest}/{item}".format(**locals()))
            for f in items:
                if os.path.isfile(f):
                    os.remove(f)
                elif os.path.isdir(f):
                    shutil.rmtree(f)

