<?php

namespace App\Http\Controllers\Function;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;

class CalcController extends Controller
{
    public function getRulesData($statement)
    {
        return DB::table('rules AS a')
            ->selectRaw('GROUP_CONCAT(b.personality_code) as personality_code, c.weight, a.statement_id')
            ->join('personalities AS b', 'a.personality_id', '=', 'b.id')
            ->join('weights AS c', 'a.weight_id', '=', 'c.id')
            ->whereIn('a.statement_id', $statement)
            ->orderBy('a.rule_code', 'asc')
            ->groupBy('a.statement_id')
            ->get();
    }

    public function mapRulesData($rulesData)
    {
        return $rulesData->map(function ($item) {
            $personalityCode = $item->personality_code;
            $weight = (string) $item->weight;
            $statementId = $item->statement_id;

            return [$personalityCode, $weight, $statementId];
        })->toArray();
    }

    public function getStatementData($rulesData)
    {
        $statementData = [];

        foreach ($rulesData as $rule) {
            $statement = DB::table('statements')
                ->select()
                ->where('id', $rule[2])
                ->get();

            if ($statement->isNotEmpty()) {
                $statementData[] = [
                    'statement_code' => $statement[0]->statement_code,
                    'statement' => $statement[0]->statement,
                ];
            }
        }

        return $statementData;
    }

    public function getPersonalitiesData()
    {
        return DB::table('personalities')
            ->selectRaw('GROUP_CONCAT(personality_code) as personality_code')
            ->get();
    }

    public function mapPersonalitiesData($personalitiesData)
    {
        return $personalitiesData->map(function ($item) {
            $personalityCode = $item->personality_code;

            // Create a new array with numeric keys
            return [$personalityCode];
        })->toArray();
    }

    public function processEvidence($rules, $personalitiesData)
    {
        //? Mendapatkan nilai FOD dari data personalitas pada indeks 0
        $fod = $personalitiesData[0][0];

        //? Inisialisasi array densitas baru.
        $newDensity = [];

        //? Jika hanya ada satu aturan, langsung kembalikan hasil perhitungan densitas baru.
        if (count($rules) == 1) {
            foreach ($rules as $rule) {
                $newDensity[$rule[0]] = (float) $rule[1];
            }

            return $newDensity;
        } else {
            //? Jika masih ada aturan yang belum diproses.
            while (!empty($rules)) {
                //? Mengambil aturan pertama dari daftar aturan.
                $densitas1[0] = array_shift($rules);

                //?  // Menghitung nilai densitas pada baris atas dari Y2.
                $densitas1[1] = [$fod, 1 - $densitas1[0][1]];

                //? Inisialisasi array densitas ke-2.
                $densitas2 = [];

                //
                if (empty($newDensity)) {
                    //nilai pada X1 baris 1
                    $densitas2[0] = array_shift($rules);
                } else {
                    foreach ($newDensity as $k => $r) {
                        //nilai pada X1 baris 2; jika ad densitas baru
                        if ($k != 'θ') {
                            $densitas2[] = [$k, $r];
                        }
                    }
                }

                $theta = 1;
                //nilai X1 baris 2 teta
                foreach ($densitas2 as $d) {
                    $theta -= $d[1];
                }
                $densitas2[] = [$fod, $theta];

                $m = count($densitas2);

                $newDensity = [];

                for ($y = 0; $y < $m; $y++) {
                    for ($x = 0; $x < 2; $x++) {
                        if (!($y == $m - 1 && $x == 1)) {
                            $v = explode(',', $densitas1[$x][0]);
                            $w = explode(',', $densitas2[$y][0]);
                            sort($v);
                            sort($w);
                            $vw = array_intersect($v, $w);
                            if (empty($vw)) {
                                $k = 'θ';
                            } else {
                                $k = implode(',', $vw);
                            }
                            if (!isset($newDensity[$k])) {
                                $newDensity[$k] = $densitas1[$x][1] * $densitas2[$y][1];
                                $k = implode(',', $vw);
                            } else {
                                $newDensity[$k] += $densitas1[$x][1] * $densitas2[$y][1];
                            }
                        }
                    }
                }

                foreach ($newDensity as $k => $d) {
                    // Periksa apakah kunci bukan θ
                    if ($k != 'θ') {
                        // Tentukan nilai untuk theta, jika tidak ada konflik maka 0
                        $thetaValue = isset($newDensity['θ']) ? $newDensity['θ'] : 0;

                        // Hitung densitas baru sesuai dengan rumus Dempster-Shafer
                        $newDensity[$k] = $d / (1 - $thetaValue);
                    }
                }

                //? Filter array dengan key theta "θ"
                $newDensity = array_filter($newDensity, function ($key) {
                    return $key !== 'θ';
                }, ARRAY_FILTER_USE_KEY);
            }
        }

        //? Mengurutkan array berdasarkan nilai dari terbesar ke terkecil
        arsort($newDensity);

        return $newDensity;
    }
}
