<?php
namespace boru\boruai\Models;

use boru\boruai\BoruAI;
use boru\boruai\Tools\PDFConverter;
use boru\query\Entity;
use boru\query\Factory;
use boru\query\models\EntityDefinition;
use boru\query\models\Value;
use boru\query\Query;
use Exception;

class Document extends Entity {
    /** @var File[] */
    private $files = [];
    public static function entityDefinition() {
        $tableName = BoruAI::table('documents');
        $query = Query::create()->select('id', 'purpose', 'reference', 'filename', 'pages', 'filesize', 'md5', 'created', 'userid', 'paged', 'summarized', 'summary', 'parsed', 'results')->from($tableName);
        return new EntityDefinition([
            "className" => static::class,
            "name" => "Document",
            "queryBase" => $query,
            "createdField" => 'created',
        ]);
    }
    public function __construct($idOrData=null) {
        parent::__construct($idOrData);
    }

    //actions

    public function updateOcr($deleteLocal=true) {
        $files = $this->files();
        $totalContent = "";
        foreach($files as $file) {
            if($file->ocrContent()) {
                $totalContent .= $file->ocrContent()."\n";
            } else {
                return;
            }
        }
        $this->summary($totalContent);
        $this->summarized(Value::functionValue("NOW()"));
        $this->save();
        if($deleteLocal) {
            $this->deleteLocalFiles();
        }
    }

    public function generateFiles($convertToPages=true,$force=false) {
        if(!BoruAI::isCLI()) {
            throw new \Exception("Document::upload() can only be done from CLI",0);
        }
        $output = [];
        $files = $this->files();
        if(empty($files) || $force) {
            $files = [];
            if($convertToPages) {
                $pdfConverter = new PDFConverter($this->filename());
                $pdfConverter->docId($this->id());
                $files = $pdfConverter->convert();
                $this->pages(count($files));
                $this->paged(Value::functionValue("NOW()"));
                $this->save();
            } else {
                $files[] = $this->filename();
            }
            foreach($files as $file) {
                if(file_exists($file)) {
                    $output[] = File::create($file,$this->id(),$this->purpose());
                }
            }
            
        }
        return $output;
    }

    public function upload($queue=true,$convertToPages=true) {
        if(!BoruAI::isCLI()) {
            throw new \Exception("Document::upload() can only be done from CLI",0);
        }
        $files = $this->files();
        if(empty($files)) {
            $files = $this->generateFiles($convertToPages);
        }
        foreach($files as $file) {
            if($queue) {
                $file->queueUpload();
            } else {
                $file->upload();
            }
        }
    }

    public function ocr($queue=true,$convertToPages=true) {
        $files = $this->files();
        if(empty($files)) {
            if($queue) {
                Queue::queue($this,"dococr");
            } else {
                $files = $this->generateFiles($convertToPages);
            }
        }
        if(!empty($files)) {
            foreach($files as $file) {
                if($queue) {
                    $file->queueOcr();
                } else {
                    $file->ocr();
                }
            }
        }
    }

    public function deleteLocalFiles() {
        $files = $this->files();
        foreach($files as $file) {
            $file->deleteLocal();
        }
    }

    public function deleteFiles() {
        $files = $this->files();
        foreach($files as $file) {
            $file->delete();
        }
    }

    // Getters and setters

    public function id($id=null) {
        if ($id !== null) {
            $this->set('id', $id);
            return $this;
        }
        return $this->get('id');
    }

    public function purpose($purpose=null) {
        if ($purpose !== null) {
            $this->set('purpose', $purpose);
            return $this;
        }
        return $this->get('purpose');
    }
    
    public function reference($reference=null) {
        if ($reference !== null) {
            $this->set('reference', $reference);
            return $this;
        }
        return $this->get('reference');
    }

    public function filename($filename=null) {
        if ($filename !== null) {
            $this->set('filename', $filename);
            $md5 = md5_file($filename);
            $filesize = filesize($filename);
            $this->md5($md5);
            $this->filesize($filesize);
            return $this;
        }
        return $this->get('filename');
    }

    public function pages($pages=null) {
        if ($pages !== null) {
            $this->set('pages', $pages);
            return $this;
        }
        return $this->get('pages');
    }

    public function filesize($filesize=null) {
        if ($filesize !== null) {
            $this->set('filesize', $filesize);
            return $this;
        }
        return $this->get('filesize');
    }

    public function md5($md5=null) {
        if ($md5 !== null) {
            $this->set('md5', $md5);
            return $this;
        }
        return $this->get('md5');
    }

    public function created($created=null) {
        if ($created !== null) {
            $this->set('created', $created);
            return $this;
        }
        return $this->get('created');
    }

    public function userid($userid=null) {
        if ($userid !== null) {
            $this->set('userid', $userid);
            return $this;
        }
        return $this->get('userid');
    }

    public function paged($paged=null) {
        if ($paged !== null) {
            $this->set('paged', $paged);
            return $this;
        }
        return $this->get('paged');
    }

    public function summarized($summarized=null) {
        if ($summarized !== null) {
            $this->set('summarized', $summarized);
            return $this;
        }
        return $this->get('summarized');
    }

    public function summary($summary=null) {
        if ($summary !== null) {
            $this->set('summary', $summary);
            return $this;
        }
        return $this->get('summary');
    }

    public function parsed($parsed=null) {
        if ($parsed !== null) {
            $this->set('parsed', $parsed);
            return $this;
        }
        return $this->get('parsed');
    }

    public function results($results=null) {
        if ($results !== null) {
            $this->set('results', $results);
            return $this;
        }
        return $this->get('results');
    }

    /**
     * 
     * @param bool $force 
     * @return \boru\boruai\Models\File[] 
     * @throws Exception 
     */
    public function files($force=false) {
        if (empty($this->files) || $force) {
            $this->files = Factory::search('File',0,0,['docid','=',$this->id()]);
        }
        return $this->files;       
    }

    // Static methods

    
    public static function exists($fileName) {
        if(file_exists($fileName)) {
            $md5 = md5_file($fileName);
            $fileSize = filesize($fileName);
            $doc = Factory::search('Document',0,1,[['md5','=',$md5],['filesize','=',$fileSize]]);
            if(!empty($doc) && is_array($doc)) {
                return $doc[0];
            }
        }
        return false;
    }

    /**
     * Create a new document
     * @param string $fileName
     * @param string $reference
     * @param array $options
     * @return Document
     */
    public static function create($fileName,$reference="",$options=[]) {
        $dupeCheck = isset($options['dupeCheck']) ? $options['dupeCheck'] : true;
        $userId = isset($options['userId']) ? $options['userId'] : -1;
        $purpose = isset($options['purpose']) ? $options['purpose'] : "assistants";
        $page = isset($options["page"]) ? $options["page"] : false;
        if($page) { $page = true; }
        $ocr = isset($options["ocr"]) ? $options["ocr"] : false;
        if($ocr) { $ocr = true; }
        if($dupeCheck) {
            $doc = static::exists($fileName);
            if($doc) {
                return $doc;
            }
        }
        $doc = new Document();
        $doc->filename($fileName);
        $doc->purpose($purpose);
        if($userId === 0) {
            $doc->set("userid",Value::functionValue("0"));
        }
        $doc->reference($reference);
        $doc->save();
        if($ocr) {
            //$doc->generateFiles();
            $doc->ocr();
        } elseif($page) {
            $doc->generateFiles();
            $doc->upload();
        }
        return $doc;
    }

    /**
     * Get a session by id
     * @param string $id
     * @return Document|false
     */
    public static function fromId($id) {
        $sessions = Factory::search("Document",[0,1],["id","=",$id]);
        if($sessions) {
            return new self($sessions[0]->id());
        }
        return false;
    }

    /**
     * List all sessions
     * @param int $limit
     * @param int $offset
     * @return Document[]
     */
    public static function listDocuments($limit=25,$offset=0) {
        return Factory::search("Document",[$offset,$limit],[1,"=",1]);
    }
}