import os
import glob
import sys

import dater
# from rexer import Rexer


class Folda:

    def __init__(self, erimp, do_verbose=False):
        self.e = erimp
        self.do_verbose = do_verbose
        return None

    def dates(self, fudi, ex_on_non_rif=False):
        # self.fudi = fudi
        e = self.e
        fufis = self.list_amf_fufis(fudi)
        out = {}
        if fufis is None:
            return None
        for fufi in fufis:
            bana = os.path.basename(fufi)
            if e.R.is_rif(bana):
                issuedate = bana[0:10]
                if issuedate not in out:
                    out[issuedate] = []
                out[issuedate].append(fufi)
            else:
                self.gripe_non_rif(fufi, ex_on_non_rif=ex_on_non_rif)
        return out

    def loose_dates(self, fudi):
        ## take a loose approach to copy with non-ernad files in NEP
        ## of form yyyy-mm-dd.amf.xml.gz
        # self.fudi = fudi
        e = self.e
        fufis = glob.glob(fudi + '/????-??-??*.amf.xml.gz')
        out = {}
        if fufis is None:
            return None
        for fufi in fufis:
            bana = os.path.basename(fufi)
            issuedate = bana[0:10]
            if issuedate not in out:
                out[issuedate] = []
            else:
                print(f"repeat of issuedate {issuedate} in {fudi}",
                      file=sys.stderr)
            out[issuedate].append(fufi)
        return out

    def dafus(self, fudi, ext=None, start=None):
        ## to be tested in plumis
        glob_string = '????-??-??'
        out = {}
        if ext is not None:
            glob_string += '*' + ext
        else:
            glob_string += '_*'
        glob_string = fudi + '/' + glob_string
        for fufi in sorted(glob.glob(glob_string), reverse=True):
            bana = os.path.basename(fufi)
            issuedate = bana[0:10]
            if start is not None and issuedate < start:
                continue
            out[issuedate] = fufi
        return out

    def has_it_issuedate(self, fudi, issuedate):
        fufis = glob.glob(fudi + '/' + issuedate + '_*')
        if len(fufis) == 0:
            return False
        return True

    def by_dates(self, fudi, ex_on_non_rif=False):
        """same as dates but allows any file type, last comes first"""
        # self.fudi = fudi
        e = self.e
        fufis = sorted(glob.glob(fudi + '/*'), reverse=True)
        out = {}
        if len(fufis) == 0:
            return None
        for fufi in fufis:
            bana = os.path.basename(fufi)
            issuedate = bana[0:10]
            if not self.e.R.rs['is_date'].match(issuedate):
                continue
            out[issuedate] = fufi
        return out

    def firsts(self, fudi, ex_on_non_rif=False, do_non_rif=False):
        """first dates"""
        self.fudi = fudi
        e = self.e
        fufis = sorted(glob.glob(self.fudi + '/*'))
        out = {}
        for fufi in fufis:
            bana = os.path.basename(fufi)
            if e.R.is_rif(bana) or do_non_rif:
                issuedate = bana[0:10]
                if issuedate not in out:
                    out[issuedate] = fufi
                else:
                    continue
            elif not do_non_rif:
                self.gripe_non_rif(fufi, ex_on_non_rif=ex_on_non_rif)
        return out

    def lasts(self, fudi, ex_on_non_rif=False):
        """last dates"""
        self.fudi = fudi
        e = self.e
        fufis = sorted(glob.glob(self.fudi + '/*'))
        out = {}
        for fufi in fufis:
            bana = os.path.basename(fufi)
            if e.R.is_rif(bana):
                issuedate = bana[0:10]
                out[issuedate] = fufi
            else:
                self.gripe_non_rif(fufi, ex_on_non_rif=ex_on_non_rif)
        return out

    def last_by_issuedate(self, fudi, issuedate):
        """last fufi for given issuedate"""
        self.fudi = fudi
        e = self.e
        fufis = sorted(glob.glob(self.fudi + '/' + issuedate + '*'))
        out_fufi = ''
        for fufi in fufis:
            bana = os.path.basename(fufi)
            if not e.R.is_rif(bana):
                continue
            out_fufi = fufi
        return out_fufi

    def keep_only_last(self, fudi, issuedate, do_test=False):
        self.fudi = fudi
        fufis = sorted(glob.glob(self.fudi + '/' + issuedate + '*'))
        if len(fufis) == 0:
            return None
        fufis = fufis[:-1]
        for fufi in fufis:
            if self.do_verbose:
                print(f"folda removes {fufi}")
            if not do_test:
                os.remove(fufi)
        return fufi[0]

    def very_last(self, fudi, ex_on_non_rif=False):
        """last dates"""
        self.fudi = fudi
        last_issuedates = self.lasts(fudi, ex_on_non_rif=ex_on_non_rif)
        if len(last_issuedates) == 0:
            return None
        lasts = sorted(last_issuedates)
        lasts.reverse()
        last = lasts[0]
        return last_issuedates[last]

    def list_amf_fufis(self, folda, with_gz=True, do_warn=False):
        """from old foldas library"""
        e = self.e
        if not os.path.isdir(folda):
            if do_warn:
                print("nothing in " + folda, file=sys.stderr)
            return None
        fufis = []
        base_glob = folda + '/*' + e.ext['amf']
        for fufi in sorted(glob.glob(base_glob)):
            fufis.append(fufi)
        if not with_gz:
            return fufis
        comp_glob = base_glob + '.gz'
        for fufi in glob.glob(comp_glob):
            fufis.append(fufi)
        sorted_fufis = sorted(fufis)
        return sorted_fufis

    # # issue and version
    def isve(self, folda, do_verbose=True):
        """from old foldas library"""
        fufis = self.list_amf_fufis(folda)
        iv = {}
        for fufi in fufis:
            bana = os.path.basename(fufi)
            # # simple check
            if len(bana) < 12:
                continue
            if bana[10:11] != '_':
                continue
            issuedate = bana[0:10]
            #print(issuedate)
            if issuedate not in iv:
                iv[issuedate] = {}
                shoti = bana[11:17]
                iv[issuedate][shoti] = fufi
        #print(shoti)

    def firsts_isda_shot(self, folda, do_verbose=True):
        """from old foldas library"""
        fufis = self.list_amf_fufis(folda)
        d = {}
        for fufi in fufis:
            bana = os.path.basename(fufi)
            # # simple check
            if bana[10:11] != '_':
                continue
            issuedate = bana[0:10]
            shoti = bana[11:17]
            # print(issuedate)
            if issuedate not in d:
                d[issuedate] = shoti
                continue
            if shoti < d[issuedate]:
                d[issuedate] = shoti
        issuedates = sorted(d.keys(), key=lambda x:x.lower())
        iv = {}
        for issuedate in issuedates:
            iv[issuedate] = d[issuedate]
        return iv

    # # issue and version
    def firsts_shoti(self, folda, do_verbose=True,
                     do_warn=False):
        """from old foldas library"""
        fufis = self.list_amf_fufis(folda)
        if fufis is None:
            if do_warn:
                print("no data for " + folda, file=sys.stderr)
            return None
        d = {}
        for fufi in fufis:
            bana = os.path.basename(fufi)
            # # simple check
            if bana[10:11] != '_':
                continue
            issuedate = bana[0:10]
            shoti = bana[11:17]
            if issuedate not in d:
                d[issuedate] = shoti
                continue
            if shoti < d[issuedate]:
                d[issuedate] = shoti
        issuedates = sorted(d.keys(), key=lambda x:x.lower())
        shotis = []
        for issuedate in issuedates:
            shotis.append(d[issuedate])
        return shotis

    def dates_unique(self, fudi, ex_on_non_rif=False):
        self.fudi = fudi
        e = self.e
        fufis = glob.glob(self.fudi + '/*')
        out = {}
        for fufi in fufis:
            bana = os.path.basename(fufi)
            if e.R.is_rif(bana):
                issuedate = bana[0:10]
                if issuedate in out:
                    raise Exception(issuedate + ' twice in ' + fudi)
                out[issuedate] = fufi
            else:
                self.gripe_non_rif(fufi, ex_on_non_rif=ex_on_non_rif)
        return out

    def gripe_non_rif(self, fufi, ex_on_non_rif=False):
        if ex_on_non_rif:
            raise Exception(fufi + 'is not a rif')
        elif self.do_verbose:
            print(fufi + ' is not a rif')
        return fufi

    def last_by_mtime(self, fudi, search='*'):
        glob_string = f'{fudi}/{search}'
        fufis = glob.glob(glob_string)
        if not len(fufis):
            print("folda see nothing for '" + glob_string + "'")
            return None
        latest_fufi = max(fufis, key=os.path.getmtime)
        return latest_fufi

    def dafudi(self, fudi_big, fudi_small):
        """count date different between two fudis, not used"""
        dafu_big = self.dates_unique(fudi_big)
        dafu_small = self.dates_unique(fudi_small)
        count = 0
        for date in dafu_big:
            if date in dafu_small:
                continue
            count += 1
        return count

    def count_gap_issues(self, fudi):
        """count date different between two fudis"""
        dafu = self.dates(fudi)
        if dafu is None:
            print("folda does not see " + fudi
                  + " count_gap_issues() return None")
            return None
        count = 0
        for issuedate in self.e.issuedates:
            # # at the time of release in brown period, skip
            # # change of 2021-07-18
            if issuedate > dater.today():
                continue
            if issuedate in dafu:
                return count
            count += 1
        # # return None
        # print(issuedate)
        #dafu_small = self.dates_unique(fudi_small)
        #count = 0
        #for date in dafu_big:
        #    if date in dafu_small:
        #        continue
        #    count += 1
        return count

    def first_issuedate(self, fudi):
        dates = sorted(list(self.dates(fudi).keys()))
        return dates[0]

    def delete_by_extention(self, fudi, ext):
        if not os.path.isdir(fudi):
            print("I need a directory here", file=sys.stderr)
            return None
        if not ext.startswith('.'):
            ext = '.' + ext
        glob_string = fudi + '/*' + ext
        for fufi in glob.glob(glob_string):
            print(f"folda removes {fufi} by extension {ext}")
            os.remove(fufi)

    def get_unique(self, fudi, bana_glob, do_silent=False):
        glob_string = fudi + '/' + bana_glob
        found = glob.glob(glob_string)
        if len(found) == 1:
            return found[0]
        if len(found) == 0:
            if not do_silent:
                print("folda: no result for {glob_string}",
                      file=sys.stderr)
            return None
        if len(found) > 1:
            if not do_silent:
                print("folda: several results for {glob_string}",
                      file=sys.stderr)
            return found[0]

    def remove_all_but_recent(self, fudi, extension, do_verbose=False):
        fufis = glob.glob(fudi + '/*' + extension)
        fufis.sort(key=os.path.getmtime)
        while len(fufis) > 1:
            old_fufi = fufis.pop(0)
            if do_verbose:
                print("folda want to remove {old_fufi}")
                continue
            if os.path.isfile(old_fufi):
                os.remove(old_fufi)
        return fufis[0]

    def clear_by_prefix(self, fudi, ext, prefix, do_verbose=False):
        # do_verbose = True
        if not os.path.isdir(fudi):
            print("folda has no {fudi}", file=sys.stderr)
            return False
        if do_verbose:
            print(f"filer clears {ext} from {fudi}")
        glob_string = fudi + '/*' + ext
        for found_fufi in glob.glob(glob_string):
            if do_verbose:
                print(f"folda sees {found_fufi}")
            if os.path.basename(found_fufi).startswith(prefix):
                if do_verbose:
                    print("filer.clear_by_extension keeps " + found_fufi)
                continue
            if do_verbose:
                print("filer.clear_by_extension removes " + found_fufi)
            os.remove(found_fufi)
