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

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

try:
    import importlib.resources as pkg_resources
except ImportError:
    # Try backported to PY<37 'importlib_resources'
    import importlib_resources as pkg_resources

class Filter(object):
    def __init__(self, filter_id, filter_type, filter_param, ccd_bandpass=None):
        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.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_limiting = filter_param.param[filter_type][7]
        # self.filter_dir = filter_param.filter_dir

    def is_too_bright(self, mag):
        return mag <= self.mag_saturation - 2.5
        # return mag <= 14.0

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

    def _get_bandpasses(self, filter_dir=None, 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)
            with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + '.txt') as filter_file:
                self.filter_bandpass = galsim.Bandpass(str(filter_file), wave_type=unit)
            with pkg_resources.path('ObservationSim.Instrument.data.throughputs', self.filter_type.lower() + '_throughput.txt') as filter_file:
                bandpass_full = galsim.Bandpass(str(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()
            with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file:
                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()
            with pkg_resources.path('ObservationSim.Instrument.data.filters', self.filter_type.lower() + "_sub.list") as wave_bin_file:
                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

    def update_limit_saturation_mags(self, exptime=150., psf_fwhm=0.1969, skyFn='sky_emiss_hubble_50_50_A.dat', chip=None):
        if self.filter_type in ["GI", "GV", "GU"]:
            return
        if chip is not None:
            pix_scale = chip.pix_scale
            read_noise = chip.read_noise
            dark_noise = chip.dark_noise
            full_well = chip.full_well
        else:
            pix_scale = 0.074
            read_noise = 5.0
            dark_noise = 0.02
            full_well = 90000
        throughput_file = self.filter_type.lower() + '_throughput.txt'

        self.mag_limiting, self.mag_saturation = calculateLimitMag(psf_fwhm=psf_fwhm, pixelSize=pix_scale, throughputFn=throughput_file, readout=5.0, skyFn=skyFn, darknoise=dark_noise, exTime=exptime, fw=full_well)
