## temporary for testing
import time
from threading import Thread
import calibre_plugins.ai_custom_tag_extractor.anything_llm as anythingllm
from PyQt5.Qt import QApplication

from calibre.ebooks.metadata.book.base import Metadata
import calibre_plugins.ai_custom_tag_extractor.config as cfg

class JobThread(Thread):
    
    def __init__(self, MainGui, bookList):
        Thread.__init__(self)
        self.daemon = True
        self.MainGui = MainGui
        self.bookList = bookList
        self.PROGRESS_TOTAL_NO = 0
        self.PROGRESS_COUNT = 0
        self.SUB_PROGRESS_COUNT = 1
        self.API_SUB_PROGRESS_TOTAL = 40
        self.api_adapter = anythingllm.AnythingLLM(self.progress_reporter)
        self.SAVE_MODE = cfg.plugin_prefs[cfg.STORE_NAME][cfg.KEY_SAVE_MODE]
    
    def run(self):
        self.abort = False
        connection = self.check_connection()
        if connection == True:
            self.send_message_to_ai()
        else:
            return False
    
    def progress_reporter(self, update=None):
        self.MainGui.update_ticker(update)
        self.add_sub_progress()
        
    ## for testing progress bar
    def process_book(self, book):
        #self.bookList[book]['title'] + self.bookList[book]['book_file']
        prompts = self.MainGui.get_prompts_for_submission()
        return self.api_adapter.send_chat_message_to_ai(self.bookList[book]['book_file'], prompts)
        
    def abort_check(self):
        if self.abort:
            return True
    
    def abort_thread(self):
        self.abort = True;
        print("Aborting API Processing..")
        self.api_adapter.abort_thread()
        
    def check_connection(self):
        print("Checking Connection..")
        if self.api_adapter.authenticate():
            return True
        else:
            self.trigger_error_message("Error Connecting to "+ self.MainGui.AI_PLATFORM +", Did you launch the Platform and are the settings correct?")
            return False
        
    def trigger_error_message(self, error_message):
        print("Error:" + error_message)
        self.MainGui.stopped_extract_due_to_error()
        self.sub_status_update(error_message)
        
    def sub_status_update(self, status):
        self.MainGui.progressSubStatusLabel.setText(status)
    
    def add_progress(self):
        self.PROGRESS_COUNT += 1
        
    def add_sub_progress(self):
        self.SUB_PROGRESS_COUNT += 1
        if self.PROGRESS_TOTAL_NO < 100:
            self.MainGui.calc_progress_bar(self.SUB_PROGRESS_COUNT)
            #print("Sub Progress:" + str(self.SUB_PROGRESS_COUNT) )
    
    def set_api_sub_process_calc(self, column_count=0, base_count=20, per_column_count=6):
        if column_count > 0:
            column_addition = per_column_count * column_count
            self.API_SUB_PROGRESS_TOTAL = column_addition + base_count
        else:
            self.API_SUB_PROGRESS_TOTAL = base_count
    
    def calculate_sub_progress_total(self, booklist_count):
        self.SUB_PROGRESS_TOTAL_NO = booklist_count * self.API_SUB_PROGRESS_TOTAL
        
    def calculate_use_sub_or_main_progress(self):
        if self.PROGRESS_TOTAL_NO >= 100:
            self.API_SUB_PROGRESS_TOTAL = 1
            return self.PROGRESS_TOTAL_NO
        else:
            return self.SUB_PROGRESS_TOTAL_NO
    
    def save_current_answer(self, aid):
        id_map = {}
        custom_columns_dict = self.MainGui.gui.current_db.field_metadata.custom_field_metadata()
        valid_datatypes = ['text', 'comments', 'int', 'float', 'datetime', 'bool']
        edit_metadata_action = self.MainGui.gui.iactions['Edit Metadata']   
        book_id = self.AI_ANSWERS[aid]['bid']
        mi = Metadata(_('Unknown'))
        
        for akey, avalue in self.AI_ANSWERS[aid].get('answers',{}).items():            
            if avalue != None and avalue != "":
                mi_field = '#'+akey
                custcol = custom_columns_dict[mi_field]
                custcol['#value#'] = avalue
                mi.set_user_metadata(mi_field, custcol)
                id_map[book_id] = mi
        
        ## process        
        QApplication.instance().processEvents()
        try:
            if len(id_map) > 0:
                edit_metadata_action.apply_metadata_changes(id_map, callback=None, merge_tags=True, merge_comments=False)
        except Exception as e:
            print("ERROR in:  edit_metadata_action.apply_metadata_changes:  ",str(e))
        QApplication.instance().processEvents()
        self.AI_ANSWERS.pop(aid, None)
    
    def send_message_to_ai(self):        
        if self.bookList != None and len(self.bookList) > 0:
            #print(self.bookList)
            self.PROGRESS_TOTAL_NO = len(self.bookList)
            self.set_api_sub_process_calc( self.MainGui.COLUMN_WIDGET_VISIBLE_COUNT, 20, 6 )
            self.calculate_sub_progress_total(self.PROGRESS_TOTAL_NO)
            self.MainGui.workout_percentage( self.calculate_use_sub_or_main_progress() )
            self.add_progress()
            print("Extracting Tags...")
            self.AI_ANSWERS = {}
            for book in self.bookList:
                ## run through each book sending the data to the LLM
                book_title_crop = (self.bookList[book]['title'][:75] + '..') if len(self.bookList[book]['title']) > 75 else self.bookList[book]['title']
                current_update = "(" + str(self.PROGRESS_COUNT) + "/" + str(self.PROGRESS_TOTAL_NO) +") " + book_title_crop                
                self.MainGui.progressStatusLabel.setText(current_update)
                # compile answers
                answers = self.process_book(book)
                self.AI_ANSWERS[book] = {'bid': self.bookList[book]['bid'], 'title': self.bookList[book]['title'], 'answers': answers }                
                print('------------------------------------------------------------')
                if self.SAVE_MODE == "AutoSave":
                    self.save_current_answer(book)
                if self.abort_check():
                    break
                #self.MainGui.calc_progress_bar(self.PROGRESS_COUNT)
                self.MainGui.calc_progress_bar(self.PROGRESS_COUNT * self.API_SUB_PROGRESS_TOTAL)
                self.add_progress()
            self.MainGui.AI_ANSWERS = self.AI_ANSWERS
            del self.AI_ANSWERS
            if self.SAVE_MODE == "Review":
                self.MainGui.reviewDialogCheckbox.setChecked(True)
            self.MainGui.extract_complete()
                