<?php

namespace App\Http\Resources;

use App\Models\Document;
use Illuminate\Http\Resources\Json\JsonResource;

class SearchResource extends JsonResource
{
    protected int $characters;
    protected string $q;

    public function __construct($resource, string $q, int $characters = 150) {
        parent::__construct($resource);

        $this->characters = $characters;
        $this->q = $q;
    }

    /**
     * Transform the resource into an array.
     *
     * @param \Illuminate\Http\Request $request
     * @return array
     */

    public function toArray($request)
    {
        $result = [
            'search'        => $this->stringRangeMatch($this->search_content, $this->characters, $this->q, '<||>'),
            'title'         => $this->title,
            'url'           => $this->lang_uri ? $this->lang_uri : '/' . $this->lang_slug,
            'contentType'   => $this->content_type
        ];

        switch (get_class($this->objectable)) {
            case Document::class:
                $result['document'] = new DocumentResource($this->objectable);
                break;
        }

        return $result;
    }

    private function stringRangeMatch($string, $characters = null, $word, $match = '') {
        $searchResults = array_filter(explode($match, $string));
        $stringToReturn = '';
        if (count($searchResults) > 0) {

            $searchKey = false;
            foreach ($searchResults as $key => $value) {
                if (empty($stringToReturn)) {
                    $stringToReturn = $searchResults[$key];
                }
                if (stripos($value, $word) !== FALSE) {
                    $word = substr($value, stripos($value, $word), strlen($word));
                    $searchKey = $key;
                }
            }
            if ($searchKey) {
                $stringToReturn = $searchResults[$searchKey];
                $characters = $characters - strlen($word);
                $halfCharacters = round($characters / 2, 0, PHP_ROUND_HALF_DOWN);
                $wordExploded = explode(strtolower($word), strtolower($stringToReturn));
                $beforeWord = $wordExploded[0];
                $afterWord = $wordExploded[1];

                if (strlen($stringToReturn) > $characters){
                    if (strlen($beforeWord) < $halfCharacters) {
                        $leftSide = substr($beforeWord, strlen($beforeWord));
                        $rightSide = substr($afterWord, 0, strripos(substr($afterWord, 0, $halfCharacters + ($halfCharacters - strlen($beforeWord))), ' ')) . '...';
                    } elseif (strlen($afterWord) < $halfCharacters) {
                        $leftSide = '...' . substr($beforeWord, 0, strripos(substr($beforeWord, 0, $halfCharacters + ($halfCharacters - strlen($afterWord))), ' ')) . ' ';
                        $rightSide = substr($afterWord, 0, strlen($afterWord));
                    } else {
                        $leftSide = '...' . ltrim(substr($beforeWord, strripos(substr($beforeWord, 0, strlen($beforeWord) - $halfCharacters), ' ')));
                        $rightSide = substr($afterWord, 0, strripos(substr($beforeWord, 0, $halfCharacters), ' ')) . '...';
                    }
                    $stringToReturn = $leftSide . '<b>' . $word . '</b>' . $rightSide;
                } else {
                    $stringToReturn = $beforeWord . '<b>' . $word . '</b>' . $afterWord;
                }
            }
        }
        return $stringToReturn;
    }
}
