<?php
namespace boru\boruai\Models\Functions;

use boru\boruai\BoruAI;
use boru\boruai\Models\ToolDefinition;
use boru\boruai\Models\Tool;
use boru\output\Output;

abstract class FunctionBase {

    /**
     * @deprecated Use functionDefinitions() instead.
     * 
     * @return ToolDefinition[]
     */
    public static function functionDefintions() {
        static::functionDefinitions();
    }

    /**
     * Return an array of function definitions
     * 
     * @return ToolDefinition[]
     */
    public static function functionDefinitions() {
        return [];
    }



    protected static $debug = false;
    protected static $debugOutput = false;
    protected static $isInit = false;
    protected static $statusCallback = true;
    protected static $formatArrayResultAsText = true;

    public static function init() {
        if(static::$isInit) {
            return;
        }
        static::$isInit = true;
        BoruAI::printToolDebug(static::class."::init()");
    }

    public static function formatArrayResultAsText($value = null)
    {
        if ($value !== null) {
            static::$formatArrayResultAsText = $value ? true : false;
        }
        return static::$formatArrayResultAsText;
    }

    public static function debug($debug=null) {
        if($debug !== null) {
            static::$debug = $debug;
        }
        return static::$debug;
    }
    public static function debugOutput($debugOutput=null) {
        if($debugOutput !== null) {
            static::$debugOutput = $debugOutput;
        }
        return static::$debugOutput;
    }
    public static function statusCallback($statusCallback=null) {
        if($statusCallback !== null) {
            static::$statusCallback = $statusCallback;
        }
        return static::$statusCallback;
    }

    
    /**
     * Return the name of the function
     * @param string $method The name of the function
     * @param Tool $tool The tool object, including the arguments, accessable via $tool->get()
     * @return mixed The result of the function to be returned to the Chat/Assistant.
     */
    public static function callback($method,$tool) {
        //get the called class:
        $class = get_called_class();
        $classParts = explode("\\",$class);
        $classString = array_pop($classParts);
        BoruAI::printToolDebug($classString."::$method");
        BoruAI::printToolDebug($tool->get());
        if(method_exists($class,"init")) {
            $class::init();
        }
        $callable = null;
        if(method_exists($class,$method)) {
            $callable = [$class,$method];
        } elseif(method_exists($class,'handle')) {
            $method = 'handle';
            $callable = [$class,$method];
        }
        if($callable) {
            $result = call_user_func($callable,$tool);
            if(is_array($result)) {
                //$result = json_encode($result,JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
                // Decide whether to pretty-print as "key: value\n" or leave as array
                $formatAsText = false;
                if (property_exists($class, 'formatArrayResultAsText')) {
                    // static property on the called class
                    $formatAsText = $class::$formatArrayResultAsText;
                } else {
                    // default behavior (backwards compatible)
                    $formatAsText = true;
                }
                if ($formatAsText) {
                    $result = Tool::printArray($result);
                } else {
                    $result = json_encode($result,JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
                }
            }
            if(static::debugOutput()) {
                static::debugOutput(false);
                BoruAI::printToolDebug("$classString::$method\n Function Result:\n",$result);
                BoruAI::printToolDebug("");
            }
            return $result;
        }
        return null;
    }

    public static function statusUpdate($status) {
        if(static::$statusCallback) {
            if(is_callable(static::$statusCallback)) {
                $callback = static::$statusCallback;
                $callback($status);
            } else {
                BoruAI::printToolDebug($status);
            }
        }
    }
}