<?php

use Illuminate\Support\Str;

if (!function_exists('load_polymorphic_dependencies')) {
    function load_polymorphic_dependencies(
        Illuminate\Database\Eloquent\Collection $collection,
        $polymorphic_name,
        $model_type,
        array $relation,
        $poly_type = null,
        $poly_id = null
    ) {
        if (empty($poly_type)) {
            $poly_type = $polymorphic_name."_type";
        }

        if (empty($poly_id)) {
            $poly_id = $polymorphic_name."_id";
        }
        $new_collection = new Illuminate\Database\Eloquent\Collection();

        foreach ($collection as $model) {
            if ($model->$polymorphic_name instanceof $model_type) {
                $new_collection->add($model->$polymorphic_name);
            }
        }

        $new_collection->load($relation);
        return $collection;
    }
}

if (!function_exists('fulltext_search_term')) {
    function fulltext_search_term($term, $allInclusive = true, $wildcard = true)
    {
        if (empty($term)) {
            return $term;
        }
        $term = str_replace("@", " ", $term);
        $term = str_replace("+", " ", $term);
        $term = str_replace("-", " ", $term);
        $term = str_replace("<", " ", $term);
        $term = str_replace(">", " ", $term);
        $term = str_replace("(", " ", $term);
        $term = str_replace(")", " ", $term);
        $term = str_replace("~", " ", $term);
        $term = str_replace("*", " ", $term);

        $words = explode(" ", trim($term));

        $terms = array();

        foreach ($words as $word) {
            if ($wildcard) {
                $word = $word."*";
            }

            if (!empty($word) && strlen($word) > 2) {
                if ($allInclusive) {
                    $word = "+".$word;
                }

                $terms[] = $word;
            }
        }

        return implode(" ", $terms);
    }
}

// Return Key Encrypter
if (!function_exists('getEncrypter')) {
    function getEncrypter($key)
    {
        if (Str::startsWith($key, 'base64:')) {
            $key = base64_decode(substr($key, 7));
        }
        return new Illuminate\Encryption\Encrypter($key, config("app.cipher"));
    }
}

/**
 *  Adds pagination key to query.
 *
 * @param \Illuminate\Encryption\Encrypter $encrypter
 * @param \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder $query
 * @param string $pageKey
 * @param string $orderFieldName DB field name used for ordering the list
 * @param string $orderDirection What is the order direction. Possible values are '<' or '>'
 * @param string $tieBreakFieldName DB field name used for ordering the list when records have the same value on $orderFieldName (usually it the DB table PK)
 *
 */
if (!function_exists('addNextKeyToQuery')) {
    function addNextKeyToQuery(Illuminate\Encryption\Encrypter $encrypter, $query, $pageKey, $orderFieldName, $orderDirection, $tieBreakFieldName = 'id', $reverseOrder = false)
    {
        $decryptKey = $encrypter->decrypt($pageKey);

        $lastId = $decryptKey['lastId'];
        $lastOrderValue = $decryptKey['lastOrderValue'];

        if($reverseOrder) {
            $orderDirection = $orderDirection === '>' ? '<' : '>';
        }

        if (!empty($lastOrderValue)) {
            if ($orderFieldName != $tieBreakFieldName) {
                $query->where(function ($query) use ($orderFieldName, $orderDirection, $lastId, $lastOrderValue, $tieBreakFieldName) {
                    $query->where($orderFieldName, $orderDirection, $lastOrderValue)
                        ->orWhere(function ($query) use ($orderFieldName, $lastOrderValue, $lastId, $tieBreakFieldName, $orderDirection) {
                            $query->where($orderFieldName, $lastOrderValue)
                                ->where($tieBreakFieldName, $orderDirection, $lastId);
                        });
                });
            } else {
                $query->where($orderFieldName, $orderDirection, $lastOrderValue);
            }
        }
    }
}

/**
 *  Adds pagination key to query.
 *
 * @param \Illuminate\Encryption\Encrypter $encrypter
 * @param \Illuminate\Database\Eloquent\Collection|Illuminate\Support\Collection $list
 * @param string $valueFieldName DB field name used for ordering the list
 * @param string $tieBreakFieldName DB field name used for ordering the list when records have the same value on $orderFieldName (usually it the DB table PK)
 *
 * @return string
 */
if (!function_exists('getNextKeyValue')) {
    function getNextKeyValue(Illuminate\Encryption\Encrypter $encrypter, $list, $orderFieldName, $tieBreakFieldName = "id")
    {
        $item = $list->last();

        $keyObject = [
            'lastId'         => $item->$tieBreakFieldName,
            'lastOrderValue' => $item->$orderFieldName,
        ];

        return $encrypter->encrypt($keyObject);
    }
}




