<?php

namespace Fluent\DataTables;

use Fluent\DataTables\Utilities\Config;
use Fluent\DataTables\Utilities\Request;
use Illuminate\Support\Traits\Macroable;

class DataTables
{
    use Macroable;

    /**
     * DataTables request object.
     *
     * @var \Fluent\DataTables\Utilities\Request
     */
    protected $request;

    /**
     * HTML builder instance.
     *
     * @var \Fluent\DataTables\Html\Builder
     */
    protected $html;

    /**
     * Make a DataTable instance from source.
     * Alias of make for backward compatibility.
     *
     * @param  mixed  $source
     * @return mixed
     *
     * @throws \Exception
     */
    public static function of($source)
    {
        return self::make($source);
    }

    /**
     * Make a DataTable instance from source.
     *
     * @param  mixed  $source
     * @return mixed
     *
     * @throws \Exception
     */
    public static function make($source)
    {
        get_instance()->load->config('datatables');

        $engines  = config_item('engines');
        $builders = config_item('builders');

        $args = func_get_args();
        foreach ($builders as $class => $engine) {
            if ($source instanceof $class) {
                return call_user_func_array([$engines[$engine], 'create'], $args);
            }
        }

        foreach ($engines as $engine => $class) {
            if (call_user_func_array([$engines[$engine], 'canCreate'], $args)) {
                return call_user_func_array([$engines[$engine], 'create'], $args);
            }
        }

        throw new \Exception('No available engine for ' . get_class($source));
    }

    /**
     * Get request object.
     *
     * @return \Fluent\DataTables\Utilities\Request
     */
    public function getRequest()
    {
        return new Request();
    }

    /**
     * Get config instance.
     *
     * @return \Fluent\DataTables\Utilities\Config
     */
    public function getConfig()
    {
        return new Config();
    }

    /**
     * @deprecated Please use query() instead, this method will be removed in a next version.
     *
     * @param $builder
     * @return QueryDataTable
     */
    public function queryBuilder($builder)
    {
        return $this->query($builder);
    }

    /**
     * DataTables using Query.
     *
     * @param  \Illuminate\Database\Query\Builder|mixed  $builder
     * @return DataTableAbstract|QueryDataTable
     */
    public function query($builder)
    {
        return QueryDataTable::create($builder);
    }

    /**
     * DataTables using Eloquent Builder.
     *
     * @param  \Illuminate\Database\Eloquent\Builder|mixed  $builder
     * @return DataTableAbstract|EloquentDataTable
     */
    public function eloquent($builder)
    {
        return EloquentDataTable::create($builder);
    }

    /**
     * DataTables using Collection.
     *
     * @param  \Illuminate\Support\Collection|array  $collection
     * @return DataTableAbstract|CollectionDataTable
     */
    public function collection($collection)
    {
        // return CollectionDataTable::create($collection);
    }

    /**
     * DataTables using Collection.
     *
     * @param  \Illuminate\Http\Resources\Json\AnonymousResourceCollection|array  $collection
     * @return DataTableAbstract|ApiResourceDataTable
     */
    public function resource($resource)
    {
        // return ApiResourceDataTable::create($resource);
    }

    /**
     * Get html builder instance.
     *
     * @return \Fluent\DataTables\Html\Builder
     *
     * @throws \Exception
     */
    public function getHtmlBuilder()
    {
        // if (! class_exists('\Fluent\DataTables\Html\Builder')) {
        //     throw new \Exception('Please install yajra/laravel-datatables-html to be able to use this function.');
        // }

        // return $this->html ?: $this->html = app('datatables.html');
    }
}
