import csv
import os
import shutil
from tempfile import NamedTemporaryFile

SCRIPT_DIR = os.path.dirname(__file__)
DATA_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "../data"))
FIELDNAMES = [
    "Id",
    "Publication",
    "Author",
    "Year",
    "Fields",
    "Type",
    "Publishers",
    "License",
    "LicenseShort",
    "Highlights",
    "Comments",
    "Files",
]


class CsvParser:
    def __init__(self, csv_file, image_dir):
        self.csv_file = csv_file
        self.image_dir = image_dir

    def _hasimage(self, id):
        """does this Id from the csv have an image uploaded"""
        image_jpg = os.path.join(self.image_dir, "image-{0}.jpg".format(id))
        if os.path.exists(image_jpg):
            return True
        else:
            return False

    def _getpublicationfromcsvrow(self, row):
        """get entire publication info from a csv row"""
        year = row["Year"]
        if not year:
            year = "Unknown"

        license = row["License"]
        if not license:
            license = "No license mentioned"

        pubinfo = {
            "Title": row["Publication"],
            "Author": row["Author"],
            "Year": year,
            "Fields": row["Fields"],
            "Type": row["Type"],
            "Publishers": row["Publishers"],
            "License": license,
            "Highlights": row["Highlights"],
            "Comments": row["Comments"],
            "Files": row["Files"],
            "Image": self._hasimage(row["Id"]),
        }
        return pubinfo

    def parsecsv(self):
        """Test function to inspect csv file as dict"""
        libcsv = open(os.path.join(DATA_DIR, self.csv_file), "r")
        with libcsv:
            csv_as_dict = csv.DictReader(libcsv)
        return csv_as_dict

    def getpublications(self):
        """get an overview of all publications for the main page"""
        libcsv = open(os.path.join(DATA_DIR, self.csv_file), "r")
        with libcsv:
            csv_as_dict = csv.DictReader(libcsv)
            publications = {}
            for row in csv_as_dict:
                year = row["Year"]
                if not year:
                    year = "Unknown"

                pubinfo = {
                    "Title": row["Publication"],
                    "Author": row["Author"],
                    "Type": row["Type"].lower().title(),
                    "Year": year,
                    "License": row["License"].lower().title(),
                    "Image": self._hasimage(row["Id"]),
                }
                publications[row["Id"]] = pubinfo
        return publications

    def gettypes(self):
        """for the dynamic menu get the unique types of publicatons"""
        libcsv = open(os.path.join(DATA_DIR, self.csv_file), "r")
        with libcsv:
            csv_as_dict = csv.DictReader(libcsv)
            listoftypes = []
            for row in csv_as_dict:
                lowertype = row["Type"].lower().title()
                if lowertype not in listoftypes:
                    listoftypes.append(lowertype)
        return listoftypes

    def getyears(self):
        """for the dynamic menu get the unique years for publicatons"""
        libcsv = open(os.path.join(DATA_DIR, self.csv_file), "r")
        with libcsv:
            csv_as_dict = csv.DictReader(libcsv)
            listofyears = []
            for row in csv_as_dict:
                uniqueyear = row["Year"]
                if not uniqueyear:
                    uniqueyear = "Unknown"
                if uniqueyear not in listofyears:
                    listofyears.append(uniqueyear)
        listofyears.sort()
        return listofyears

    def getlicenses(self):
        """for the dynamic menu get the unique liscenses for publicatons"""
        libcsv = open(os.path.join(DATA_DIR, self.csv_file), "r")
        with libcsv:
            csv_as_dict = csv.DictReader(libcsv)
            listoflicenses = []
            for row in csv_as_dict:
                license = row["License"].lower().title()
                if not license:
                    license = "No License Mentioned"
                if license not in listoflicenses:
                    listoflicenses.append(license)
        return listoflicenses

    def getfieldsofinterest(self):
        """for the R&R page get the fields of interest from the publicatons"""
        libcsv = open(os.path.join(DATA_DIR, self.csv_file), "r")
        with libcsv:
            csv_as_dict = csv.DictReader(libcsv)
            fieldsofinterest = {}
            for row in csv_as_dict:
                fields = row["Fields"].split(",")
                fieldsofinterest[row["Id"]] = fields
        return fieldsofinterest

    def getfullpublication(self, pubid):
        """For the single book view, most complete overview"""
        libcsv = open(os.path.join(DATA_DIR, self.csv_file), "r")
        pubinfo = {}
        with libcsv:
            csv_as_dict = csv.DictReader(libcsv)
            for row in csv_as_dict:
                if pubid == row["Id"]:
                    pubinfo = self._getpublicationfromcsvrow(row)

        # print(pubinfo)
        return pubinfo

    def generatenewpublicationid(self):
        """When uploading a book generate a new unique ID"""
        libcsv = open(os.path.join(DATA_DIR, self.csv_file), "r")
        allidsincsv = []
        with libcsv:
            csv_as_dict = csv.DictReader(libcsv)
            for row in csv_as_dict:
                allidsincsv.append(int(row["Id"]))
            return str(max(allidsincsv) + 1)

    def writepublication(self, uploadform):
        """When uploading a publication writes entry to the csv"""
        id = generatenewpublicationid()
        with open(
            os.path.join(DATA_DIR, "varlib.csv"), "a", newline=""
        ) as csvfile:
            csv_as_writer = csv.DictWriter(csvfile, FIELDNAMES=FIELDNAMES)
            csv_as_writer.writerow(
                {
                    "Id": id,
                    "Publication": uploadform.uploadpublication.data,
                    "Author": uploadform.author.data,
                    "Year": uploadform.year.data,
                    "Fields": uploadform.fields.data,
                    "Type": uploadform.type.data,
                    "Publishers": uploadform.publishers.data,
                    "License": uploadform.license.data,
                    "LicenseShort": uploadform.licenseshort.data,
                    "Highlights": uploadform.highlights.data,
                    "Comments": uploadform.comments.data,
                }
            )
            print("succesfully written book to csv")
        return id

    def editborrowedby(self, pubid, borrower):
        """Edits the borrowed by field for a publication entry in csv"""
        tempfile = NamedTemporaryFile("w+t", newline="", delete=False)
        filename = os.path.join(DATA_DIR, "varlib.csv")
        with open(filename, "r", newline="") as libcsv, tempfile:
            csv_as_dict = csv.DictReader(libcsv)
            csv_as_writer = csv.DictWriter(tempfile, FIELDNAMES=FIELDNAMES)
            # use the reader to read where, then writer to write the new row.
            csv_as_writer.writeheader()
            for row in csv_as_dict:
                if pubid == row["Id"]:
                    print("publication changes borrower")
                    print(row["Publication"])
                    row["Currently borrowed by"] = borrower
                csv_as_writer.writerow(row)

        shutil.move(tempfile.name, filename)

    def concatenate_csv_row(self, row):
        rowcontent = []
        rowcontent.append(row["Publication"])
        rowcontent.append(row["Author"])
        rowcontent.append(row["Fields"])
        rowcontent.append(row["Type"])
        rowcontent.append(row["Publishers"])
        rowcontent.append(row["Highlights"])
        rowcontent.append(row["Comments"])
        return " ".join(rowcontent)