# Created by <NAME> and <NAME>


import csv
from DataMiner import getBookInfo
from DataMiner import getBookReviews
from DataMiner import getReviewLabels
from DBManager import DataBase


# MeaningCloud different labels
sentimentLabels = ('P+', 'P', 'NEU', 'N', 'N+', 'NONE')
agreementLabels = ('AGREEMENT', 'DISAGREEMENT')
subjectivityLabels = ('OBJECTIVE', 'SUBJECTIVE')
ironyLabels = ('NONIRONIC', 'IRONIC')


def getLabels(isbn):
	"""
	Performs the calls to GoodReads miner function and combines it with the
	MeaningCloud one, in order to obtain the final set of labels

	:param isbn: Identification number of a book
	:return: 4 dictionaries containing each parameter label counters

	"""

	# GoodReads web page scraping to obtain book reviews
	reviews = getBookReviews(isbn)

	# Defining counter dictionaries
	sentiment = dict.fromkeys(sentimentLabels, 0)
	agreement = dict.fromkeys(agreementLabels, 0)
	subjectivity = dict.fromkeys(subjectivityLabels, 0)
	irony = dict.fromkeys(ironyLabels, 0)

	# For each review text, obtain each of the labels
	for text in reviews:
		se, ag, su, ir = getReviewLabels(text)

		# Update the counters, if the returned value is not None
		try:
			sentiment[se] += 1
		except KeyError:
			pass
		try:
			agreement[ag] += 1
		except KeyError:
			pass
		try:
			subjectivity[su] += 1
		except KeyError:
			pass
		try:
			irony[ir] += 1
		except KeyError:
			pass

	return sentiment, agreement, subjectivity, irony


def fillDB(maxInsertions):
	"""
	Main function to fill the database with the information we can extract from
	each book specified in the books CSV.

	We obtain the information from 3 sources:
	- Google Books API
	- GoodReads web page
	- MeaningCloud API

	:param maxInsertions: maximum number of desired books insertions

	"""

	db = DataBase()

	# Creation of the recovery backup file
	recoveryFile = open("/home/integracion/Documentos/Integration-Books-master/files/backup.txt", 'a+', encoding="UTF-8")

	# Defining the books reader
	booksFile = open("/home/integracion/Documentos/Integration-Books-master/files/books.csv", 'r', encoding="UTF-8")
	booksReader = csv.DictReader(booksFile)

	# Counting the number of inserted books
	bookInsertions = 0

	for entry in booksReader:

		# If the maximum number of desired insertions is reached, stop
		if bookInsertions >= maxInsertions:
			break

		# The unique identifier of each book is extracted and formatted
		isbn = entry["isbn"].zfill(10)

		# Then we check if an entry with the same ISBN already exists
		existence = db.checkExistence("books", {"ISBN": isbn})
		if existence:
			continue

		try:
			# Each book properties are extracted and formatted
			book = {
				"ID":                   int(entry["goodreads_book_id"]),
				"ISBN":                 isbn,
				"Authors":              entry["authors"],
				"Publication_Year":     float(entry["original_publication_year"]),
				"Title":                entry["original_title"],
				"Language":             entry["language_code"],
				"Average_Rating":       float(entry["average_rating"]),
				"Total_Ratings":        int(entry["ratings_count"]),
				"Ratings": {
					"1":                int(entry["ratings_1"]),
					"2":                int(entry["ratings_2"]),
					"3":                int(entry["ratings_3"]),
					"4":                int(entry["ratings_4"]),
					"5":                int(entry["ratings_5"])
				}
			}

			# Google Books API request
			publisher, price, genre = getBookInfo(isbn)
			book.update({
				"Publisher": publisher,
				"Price": price,
				"Genre": genre
			})

			# TODO: Continue if there is neither publisher nor genre?

			# GoodReads and MeaningCloud reviews labels extraction
			sentiment, agreement, subjectivity, irony = getLabels(isbn)
			book.update({
				"Sentiment": sentiment,
				"Agreement": agreement,
				"Subjectivity": subjectivity,
				"Irony": irony
			})

			# The book is written into the back up file
			recoveryFile.write(str(book) + "\n")

			# Final insertion into the Database
			db.insert("books", book)
			bookInsertions += 1

		# In case there is an empty string as value in any of the fields
		except ValueError:
			print("ERROR: Can not insert", entry["book_id"])

	recoveryFile.close()
	booksFile.close()


if __name__ == "__main__":

	# As each insertion is around 30 secs: 1000 insertions take 8.3 hours
	fillDB(maxInsertions=float("inf"))
