<?php
namespace App\Http\Traits;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
trait QueryGeneratorTrait {
    public $query, $table, $selectColumns, $data, $pageOpt;

    public $except = [];

    // $except - Array - [ 'table_name' => ['except_column'] ]
    protected function setSelectColumns () {
        $except = $this->except;
        $mergedColumns = [];
        foreach ($this->table as $key => $item) {
            // Column Listing - Tabloya Ait Kolon Adları Değişkene Atılıyor.
            $columns[$key] = Schema::getColumnListing($item['name']);
            // Except Columns - Tablodan Hariç Tutulan Kolonlar Siliniyor.
            if (count($except) > 0) {
                if (isset($except[$item['name']])) {
                    foreach ($except[$item['name']] as $exceptItem) {
                        $index = array_search($exceptItem, $columns[$key]);
                        array_splice($columns[$key], $index , 1);
                    }
                }
            }
            // AS Columns - Farklı Tablolardaki Aynı Kolon İsimleri Karışmaması İçin Yapılıyor.
            $asColumns = [];
            foreach ($columns[$key] as $column) {
                $asColumns[] = $item['name'] . '.' . $column . ' as ' . $item['name'] . '.' . $column;
            }
            $mergedColumns = array_merge($mergedColumns, $asColumns);
        }
        $this->selectColumns = $mergedColumns;
        return $this;
    }

    protected function setQuery($request, $defaultOrderCol = null, $where = null) {
        $this->setSelectColumns();
        // ---- DB QUERY ---- //
        $this->query = DB::table($this->table[0]['name'])->select($this->selectColumns);
        for($i = 1;  $i < count($this->table); $i++) {
            if (isset($this->table[$i]['foreignId']) && $this->table[$i]['relationId']) {
                $this->query->join($this->table[$i]['name'], $this->table[$i]['foreignId'], $this->table[$i]['relationId']);
            }
        }
        // ---- ORDER BY ---- //
        if ($request->has('order') && $request->has('order-column')) {
            $orderText = $request->input('order-column');
            if (count(explode('.', $orderText)) <= 1) {
                $orderText = $this->table[0]['name'] . '.' . $orderText;
            }
            $this->query->orderBy($orderText, $request->order);
        } else if (isset($defaultOrderCol)) {
            $this->query->orderBy($defaultOrderCol, 'desc');
        }
        // ---- WHERE ---- //
        if (isset($where)) {
            if (is_array($where)) {
                $this->query->where($where[0], '=', $where[1]);
            } else if (is_callable($where)) {
                $this->query->where($where);
            }
        }
        // ---- SEARCH ---- //
        if ($request->has('search') && $request->has('search-columns')) {
            $search = $request->search;
            $columns = json_decode($request->input('search-columns'));
            foreach ($columns as $column) {
                if (count(explode('.', $column)) <= 1) {
                    $newColumns[] = $this->table[0]['name'] . '.' . $column;
                } else {
                    $newColumns[] = $column;
                }
            }
            $this->query->where(function ($query) use ($newColumns, $search) {
                foreach ($newColumns as $column) {
                    $query->orWhere($column, 'LIKE', '%' . $search . '%');
                }
            });
        }
        // ---- PAGINATE ---- //
        $this->data = $this->query->paginate(10);
        // ---- COLLECTION ---- //
        $this->pageOpt  = collect($this->data)->except('data');
        $this->data     = collect($this->data)->only('data')['data'];

        return $this;
    }

    protected function setCollection() {
        $data = [];
        $idStore = [];
        $dumpData = [];
        $index = -1;
        foreach ($this->data as $rowInd => $rowVal) {
            $gate = true;
            $index++;
            foreach ($rowVal as $colInd => $colVal) {
                if ($colInd == $this->table[0]['name'] . ".id") {
                    $searchIndex = array_search($colVal, $idStore);
                    if ($searchIndex === false) {
                        $idStore[] = $colVal;
                    } else {
                        $gate = false;
                    }
                }

                $tableName = explode('.', $colInd)[0];
                $tableColName = explode('.', $colInd)[1];
                if ($tableName == $this->table[0]['name']) {
                    if ($gate == true) {
                        $data[$index][$tableColName] = $colVal;
                    } else {
                        $dumpData[$index][$tableColName] = $colVal;
                    }
                }
                else {
                    if ($gate == true) {
                        $data[$index][$tableName][$tableColName] = $colVal;
                    } else {
                        $dumpData[$index][$tableName][$tableColName] = $colVal;
                    }
                }
            }
            if (!$gate) {
                $index--;
            }
        }
        foreach ($this->pageOpt as $key => $value) {
            $lastCollection[$key] = $value;
        }
        $lastCollection['data'] = json_decode(json_encode($data));
        $this->data = $lastCollection;
        return $this->data;
    }
}