"""
Copyright (C) 2017-2021 OceanDataLab
This file is part of skiMulator.

skimulator is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

skimulator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with skiMulator.  If not, see <http://www.gnu.org/licenses/>.
"""
""" Attitude (yaw and aocs) signal"""

import sys
import numpy
from scipy import interpolate
from typing import Dict, Tuple
import netCDF4
import datetime
from .. import fitspline2d
from .. import const
import logging
logger = logging.getLogger(__name__)

def load_yaw_aocs(yaw_file: str) -> Tuple[numpy.ndarray, numpy.ndarray]:
    fid = netCDF4.Dataset(yaw_file, 'r')
    time = fid.variables['time'][:]
    time = time / 86400.
    yaw_microrad = fid.variables['yaw1'][:]
    fid.close()
    return time, yaw_microrad


def make_yaw_aocs(time_yaw: numpy.array, vac_yaw: numpy.array,
                  time: numpy.array) -> numpy.ndarray:
    max_yaw = numpy.max(time_yaw)
    # ind_time = numpy.where(time > max_yaw)
    # time[ind_time] = time[ind_time] - max_yaw
    time = time * 86400
    time = numpy.mod(time, max_yaw)
    f = interpolate.interp1d(time_yaw, vac_yaw)
    yaw_aocs = f(time)
    return yaw_aocs


def make_yaw_ted(time: numpy.array, cycle: float, angle: numpy.array,
                 first_time: datetime.datetime, beam: float,
                 instr_conf: str) -> numpy.array:
    import pkg_resources
    nxspline, nyspline, thedeg = (128, 64, 12)
    bn = f'Spline_{nxspline:d}_{nyspline:d}_TED_'
    if instr_conf == 'A':
        fname = f'{bn}TAS_{beam:d}_DEG.npy'
    else:
        fname = '{bn}CB_{beam:d}_DEG.npy'

    coeff_path = pkg_resources.resource_filename('skimulator',
                                                 'share/{}'.format(fname))

    wres = numpy.load(coeff_path)
    param = fitspline2d.ted_tas(wres, nxspline, nyspline, thedeg)
    # Convert time in seconds
    time = numpy.mod(time, cycle) * 86400
    # Normalize time between 0 and 1 by dividing by the total seconds in 
    # 1 orbit and shift for 0s at 0deglat ascending
    max_time_orbit = 6083.
    # max_time_orbit = max(6083, numpy.max(time))
    tdec = 5.622404310127427501e-02 * 86400
    t_orbit = numpy.mod(time - tdec, max_time_orbit) / max_time_orbit
    # Shift angle to across track, clockwise
    az = numpy.mod(-1 * numpy.rad2deg(angle), 360)
    # Normalize date between 0 and 1 for seasonal cycle
    date_start = datetime.datetime(first_time.year, 1, 1)
    time_d = (first_time - date_start).total_seconds()
    date_end = datetime.datetime(first_time.year, 12, 31, 23, 59, 59)
    time_total = (date_end - date_start).total_seconds()
    time_d = numpy.mod(time_d + time, time_total) / time_total
    # RESULTAT EN ARCSEC
    # if (t_orbit < 0).any() or (t_orbit < 1).any() or (az < 0).any()
    # or (az > 360).any() or (time_d <0).any() or (time_d>1).any():
    #    print(t_orbit, az, time_d)
    yaw_ted = (param.transform(t_orbit, az, time_d)).astype('float32')
    # conversion in rad
    yaw_ted = yaw_ted * numpy.pi * 10**6 / (180 * 3600)
    return yaw_ted


class Attitude():
    '''Class attitude defines the yaw from ted and aocs
    Args: 
        parameters ()
    '''

    def __init__(self, parameters):
        import pkg_resources
        self.coeff_path_avv6 = pkg_resources.resource_filename('skimulator',
                                     'share/AVV_6deg.npy')
        self.coeff_path_avv12 = pkg_resources.resource_filename('skimulator',
                                 'share/AVV_12deg.npy')
        self.coeff_path_std6 = pkg_resources.resource_filename('skimulator',
                                 'share/AVV_6deg.npy')
        self.coeff_path_std12 = pkg_resources.resource_filename('skimulator',
                                 'share/AVV_6deg.npy')

        self.DT_ORBIT = 6083
        self.n12deg = parameters.list_angle.count(12)
        self.nbeam = (self.n12deg + parameters.list_angle.count(6))
        self.instr_configuration = parameters.instr_configuration
        self.time_yaw, self.vac_yaw = load_yaw_aocs(parameters.yaw_file)
        l_angle = [[0,], parameters.list_angle]
        # Flatten list
        self.beam_angle = [item for sublist in l_angle for item in sublist]


    def load_coefficient():
        '''not used'''
        self.avv6 = numpy.load(coeff_path_avv6)
        self.std6 = numpy.load(coeff_path_std6)
        self.avv12 = numpy.load(coeff_path_avv12)
        self.std12 = numpy.load(coeff_path_std12)


    def generate(self, time:numpy.array, ti_cycle: float, ac_angle: numpy.array,
                 first_time: datetime.datetime)-> Dict[str, numpy.ndarray]:
        '''Generate AOCS and TED attitude signal'''
        yaw_aocs_all = []
        yaw_ted_all = []
        yaw_total_all = []
        for b in range(len(self.beam_angle)):
            yaw_aocs = make_yaw_aocs(self.time_yaw, self.vac_yaw, time[:, b])
            if b !=0:
                yaw_ted = make_yaw_ted(time[:, b], ti_cycle, ac_angle[:, b-1],
                                       first_time, self.beam_angle[b],
                                       self.instr_configuration)
            else:
                yaw_ted = 0 * yaw_aocs
            # Conversion from microrad to m/s
            yaw_total = ((yaw_aocs + yaw_ted) * const.vsat * 10**(-6)
                         * numpy.cos(ac_angle[:, b - 1]))
            yaw_aocs_all.append(yaw_aocs)
            yaw_ted_all.append(yaw_ted)
            yaw_total_all.append(yaw_total)
        yaw_aocs_all = numpy.transpose(numpy.array(yaw_aocs_all))
        yaw_ted_all = numpy.transpose(numpy.array(yaw_ted_all))
        yaw_total_all = numpy.transpose(numpy.array(yaw_total_all))
        return {"yaw" : yaw_total_all, "yaw_aocs": yaw_aocs_all,
                "yaw_ted": yaw_ted_all}


    def calc(self, radial_angle, time):
        '''not finished'''
        pidx = ((128 * radial_angle / numpy.pi / 2
                + 0.49999).astype('int')) % 128
        oidx = ((64*(3600*24*(time)) / self.DT_ORBIT
                + 0.49999).astype('int')) % 64
        nx, ny = radial_angle.shape
        res = numpy.zeros([nx,ny])
        noise = numpy.random.randn(nx,ny)


