import glob
import os
import subprocess
import numpy as np
import pandas as pd
import datetime as dt
# from PyGMTSAR import convertIntfIn  # One day this will break and you will need to find its new home


def archiveIntfs(intf_dir, archive_dates):
    """
    Archive interferograms which use noisy acquisitions.
    Automatically handles list or file path for 'archive_dates'
    INPUT:
    intf_dir - path to host directory for interferogram directories (i.e. 'f2/intf_all')
    archive_dates - list of dates in GMTSAR date format of noisy dates
    """

    # Read in archive_dates if data file
    date_list = []

    if type(archive_dates) == str:
        with open(archive_dates, 'r') as file:
            for line in file:
                date_list.append(line[-1])
                print(line)

    elif type(archive_dates) == list:
        date_list = archive_dates

    # If not existant, create archive directory
    archive_path = '{}/archived_intfs'.format(intf_dir)

    if len(glob.glob(archive_path)) == 0:
        print('Creating ' + archive_path)
        subprocess.call("mkdir {}/archived_intfs".format(intf_dir), shell=True)

    # Get list of interferograms to archive
    archive_list = []

    print()
    print('Searching for dates containing: ')
    for date in date_list:
        print(date)
        archive_list.extend(glob.glob(date + '_*'))  # Masters
        archive_list.extend(glob.glob('*_' + date))  # Repeats

    # Move to archive directory
    print()
    print('Archiving {} interferograms'.format(len(archive_list)))
    for intf in archive_list:
        subprocess.call('mv ' + intf + ' ' + archive_path, shell=True)


def selectIntfs(tablePath, method, tMin, tMax, **kwargs):
    """
    ========================== INPUTs: ==========================
    tablePath - Path to baseline_table.dat generated by GMTSAR
    method - 'sequential' for nth nearest neighbor pair(s) or 'baseline' for temporal baseline

    If 'sequential' is selected:
        tMin - minimum nearest-neighbor pair threshold
        tMax - maximum nearest-neighbor pair threshold

    If 'baseline' is selected:
        tMin - minimum allowable temporal baseline (days)
        tMax - maximum allowable temporal baseline (days)

    Optional:
    requiredDates -
    # orbitMin - minimum allowable orbital baseline (m)
    # orbitMax - maximum allowable orbital baseline (m)
    plotMatrix - set to True to visualize interferogram pairs
    printList - print intfIn to command line
    writeList - write intfIn to file named 'intf.in'

    ========================== OUTPUTS: ==========================
        intfIn - list of interferogram pair filestems formatted for intf_tops.csh
                 ex: 'S1_20141108_ALL_F2:S1_20150823_ALL_F2'
        plotIn - input DataFrame for plotNetwork. Contains 'Master' and 'Repeat' columns

    """
    # Handle kwarg options

    plotMatrix = False
    printList = False
    writeList = False

    if 'plotMatrix' in kwargs:
        plotMatrix = kwargs['plotMatrix']

    if 'printList' in kwargs:
        printList = kwargs['printList']

    if 'writeList' in kwargs:
        writeList = kwargs['writeList']

    # Load data
    pd.set_option('display.float_format', lambda x: '%f' % x)  # Display without exponential
    baselineTable = pd.read_csv(tablePath, header=None, sep=' ')  # Read table
    baselineTable.columns = ['Stem', 'numDate', 'sceneID', 'parBaseline', 'perpBaseline']
    baselineTable['Dates'] = pd.to_datetime(baselineTable['Stem'].str.slice(start=15, stop=23))  # Scrape dates
    baselineTable = baselineTable.sort_values(by='numDate')

    N = len(baselineTable)  # Number of aquisitions
    ID = np.zeros((N, N))  # Interferogram pair key matrix (1 to make intf, 0 for no intf)

    # Print info
    if method == 'sequential':
        print('Creating list of {} to {} nearest-neighbor interferograms...'.format(tMin, tMax))

    elif method == 'baseline':
        print('Creating list of interferograms with baselines between {} to {} days...'.format(tMin, tMax))
    else:
        print("Please set method to 'sequential' or 'baseline'")
        return

    # Use input nearest-neighbor order range tMin and tMax to specify which interferogram keys to 'turn on'
    for masterID, row in enumerate(ID):
        for repeatID, value in enumerate(row):

            # Select pairs based on specified method:
            if method == 'sequential':

                # If difference in numerical scene ID is within allowed range, mark as true
                if abs(masterID - repeatID) != 0 and abs(masterID - repeatID) >= tMin and abs(masterID - repeatID) <= tMax:
                    ID[masterID, repeatID] = 1

            elif method == 'baseline':

                # Get absolute value of perpendicular baseline
                baseline = abs(baselineTable['perpBaseline'][repeatID] - baselineTable['perpBaseline'][masterID])

                # If difference in temporal baseline is within allowed range, mark as true
                if baseline >= tMin and baseline <= tMax:
                    ID[masterID, repeatID] = 1

    # Create master and repeat matricies of dimension N x N
    Masters = np.array(list(baselineTable['Dates'])).repeat(N).reshape(N, N)
    Repeats = np.array(list(baselineTable['Dates'])).repeat(N).reshape(N, N).T

    # Loop through indicies to get pair dates
    intfIn = []
    dirNames = []
    for i in range(len(ID)):
        for j in range(len(ID[0])):
            if ID[i, j] == 1 and Masters[i, j] < Repeats[i, j]:  # We only want the lower half of the matrix, so ignore intf pairs where 'master' comes after 'repeat'
                intfIn.append('S1_' + Masters[i, j].strftime('%Y%m%d') + '_ALL_F2:S1_' + Repeats[i, j].strftime('%Y%m%d') + '_ALL_F2')

    # If given existing intfTable, cross-reference pairs to eliminate overlap
    if 'intfTable' in kwargs:
        print()
        print('Cross referencing interferogram list...')
        intfTable = kwargs['intfTable']
        dirNames = convertIntfIn(intfIn, 'dir', False)
        removeIntfs = []

        for i, intf in enumerate(dirNames):
            if intf in list(intfTable['DateStr']):
                removeIntfs.append((intfIn[i]))

        if len(removeIntfs) > 0:
            for intf in removeIntfs:
                intfIn.remove(intf)

    # Get number of interferogams to make
    n = len(intfIn)
    print('Number of new interferograms to be made: {}'.format(n))

    # Output dataframe instead
    plotIn = pd.DataFrame()
    plotIn['Master'] = [dt.datetime.strptime(date[3:11], '%Y%m%d') for date in intfIn]
    plotIn['Repeat'] = [dt.datetime.strptime(date[22:30], '%Y%m%d') for date in intfIn]

    # Print list
    if printList == True:
        for intf in intfIn:
            print(intf)

    # Plot interferogram matrix
    if plotMatrix == True:
        plt.rcParams['xtick.bottom'] = plt.rcParams['xtick.labelbottom'] = False
        plt.rcParams['xtick.top'] = plt.rcParams['xtick.labeltop'] = True

        fig = plt.figure(1, (10, 10))
        ax = plt.gca()
        ax.imshow(ID, 'binary')
        ax.set_ylabel('Master')
        ax.set_title('Repeat', size=10)

    # Write intfIn to file
    if writeList == True:
        print('Writing list of interferograms to intf.in')

        with open('intf.in', 'w') as file:
            for line in intfIn:
                file.write(line + '\n')

    return intfIn, plotIn


def renameIntfs(searchStr, format):
    # Rename interferogram directories based off of input 'format' string
    # 'GMTSAR' for YYYYJJJ minus one day
    # 'CANDIS' for YYYYMMDD

    dirList = glob.glob(searchStr)
    print(dirList)

    for dirName in dirList:
        if format == 'GMTSAR':
            if int(dirName[-7:]) < 2000000:

                tempDate1 = dt.datetime.strptime(dirName[-17:-9], '%Y%m%d') - dt.timedelta(days=1)
                tempDate2 = dt.datetime.strptime(dirName[-8:], '%Y%m%d') - dt.timedelta(days=1)
                newDirName = tempDate1.strftime('%Y%j') + '_' + tempDate2.strftime('%Y%j')
                os.rename(dirName, newDirName)

        elif format == 'CANDIS':

            # print('Searching: ' + dirName[-15:] + "/*SLC")
            SLCs = glob.glob(dirName[-15:] + "/*SLC")
            # print(SLCs)
            # Add their dates to the date1 and date2 image lists
            date1 = (SLCs[0][19:27])
            date2 = (SLCs[1][19:27])
            newDirName = date1 + '_' + date2
            # print(newDirName)
            os.rename(dirName, newDirName)

    # return output_list
