import galsim
import pylab as pl
import os
import numpy as np

from ObservationSim.Instrument._util import photonEnergy
from ObservationSim.Instrument.FilterParam import FilterParam

class Filter(object):
    def __init__(self, filter_id, filter_type, filter_param, ccd_bandpass):
        self.filter_id = filter_id
        self.filter_type = filter_type
        self.ccd_bandpass = ccd_bandpass
        self._getParam(filter_param, filter_type)
        if self.filter_dir is not None:
            self.bandpass_full, self.bandpass_sub_list = self._get_bandpasses(self.filter_dir)
        self.survey_type = self._getSurveyType()

    def _getSurveyType(self):
        if self.filter_type in ["GI", "GV", "GU"]:
            return "spectroscopic"
        else:
            return "photometric"

    def _getParam(self, filter_param, filter_type, filter_id=None):
        self.effective_wavelength = filter_param.param[filter_type][0]
        self.effective_width = filter_param.param[filter_type][1]
        self.blue_limit = filter_param.param[filter_type][2]
        self.red_limit = filter_param.param[filter_type][3]
        self.efficiency = filter_param.param[filter_type][4]
        self.sky_background = filter_param.param[filter_type][5]
        self.mag_saturation = filter_param.param[filter_type][6]
        self.mag_dim = filter_param.param[filter_type][7]
        self.filter_dir = filter_param.filter_dir

    def is_too_bright(self, mag):
        return mag <= self.mag_saturation - 1.0

    def is_too_dim(self, mag):
        return mag >= self.mag_dim + 1.0

    def _get_bandpasses(self, filter_dir, unit='A'):
        if self.filter_id < 7:  # Photometric
            # Get full-bandpass
            filter_file = os.path.join(filter_dir, self.filter_type+".dat")
            bandpass_full = galsim.Bandpass(filter_file, wave_type=unit)
            bandpass_full = bandpass_full * self.ccd_bandpass

            # Get sub-bandpasses
            bandpass_sub_list = []
            wave_bin_file = os.path.join(filter_dir, self.filter_type.lower() + "_sub.list")
            wave_points = open(wave_bin_file).read().splitlines()

            for i in range(2, len(wave_points), 2):
                blim = max(float(wave_points[i-2])*0.1, bandpass_full.blue_limit)
                rlim = min(float(wave_points[i])*0.1, bandpass_full.red_limit)
                if blim >= rlim:
                    continue
                bandpass = bandpass_full.truncate(blue_limit=blim, red_limit=rlim)
                bandpass_sub_list.append(bandpass)
            # print("num of sub-bandpasses for filter#%d(%s) = "%(self.filter_id, self.filter_type), len(bandpass_sub_list), flush=True)
        else:   # Spectroscopic
            sls_lamb = np.linspace(self.blue_limit, self.red_limit, 100)
            sls_flux = np.ones_like(sls_lamb)
            con_spec = galsim.LookupTable(sls_lamb, sls_lamb, interpolant='nearest')
            bandpass_full = galsim.Bandpass(con_spec, wave_type=unit)
            bandpass_sub_list = []
            wave_bin_file = os.path.join(filter_dir, self.filter_type.lower() + "_sub.list")
            wave_points = open(wave_bin_file).read().splitlines()
            for i in range(2, len(wave_points), 2):
                blim = max(float(wave_points[i - 2]) * 0.1, bandpass_full.blue_limit)
                rlim = min(float(wave_points[i]) * 0.1, bandpass_full.red_limit)
                if blim >= rlim:
                    continue
                bandpass = bandpass_full.truncate(blue_limit=blim, red_limit=rlim)
                bandpass_sub_list.append(bandpass)
            # print("num of sub-bandpasses for filter#%d(%s) = " % (self.filter_id, self.filter_type), len(bandpass_sub_list), flush=True)
            
        return bandpass_full, bandpass_sub_list

    def getPhotonE(self):
        return photonEnergy(self.effective_wavelength)

    def getSkyNoise(self, exptime, gain=1.):
        return self.sky_background * exptime / gain
