<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class StoreController extends Controller {
    private $objUser;
    private $objPermission;
    private $storePath;

    public function __construct() {
        $this->storePath = storage_path('app/public/store');
        $this->objUser = new UserController();
        $this->objPermission = new PermissionController();
    }

    // Game
    public function getGames() { // /api/rpc/store/game/getgames
        return DB::table('str_games_loc')
            ->join('str_games', 'str_games.id', '=', 'str_games_loc.ref_id')
            ->get(array(
                'str_games.id',
                'str_games.name',
                'str_games_loc.name as altname'
            ));
    }

    public function getGame($id) { // /api/rpc/store/game/getgame/id
        return DB::table('str_games_loc')
            ->join('str_games', 'str_games.id', '=', 'str_games_loc.ref_id')
            ->where('str_games.id', $id)
            ->get(array(
                'str_games.id',
                'str_games.name',
                'str_games_loc.name as altname'
            ));
    }

    public function newGame(Request $r) { // /api/rpc/store/games/newgame
        $add = DB::table('str_games')
            ->insert([
                'name' => $r->name
            ]);

        return \Response::json($add);
    }

    public function editGame(Request $r) { // /api/rpc/store/games/editgame
        return DB::table('str_games')
            ->where('id', $r->id)
            ->update([
                'name' => $r->name
            ]);
    }

    // Category
    public function getCategories() { // /api/rpc/store/category/getcategories
        return DB::table('str_category_loc')
            ->join('str_category', 'str_category.id', '=', 'str_category_loc.ref_id')
            ->get(array(
                'str_category.id',
                'str_category.name',
                'str_category_loc.name as altname',
                'str_category.game_id',
                'str_category.min_screenshots'
            ));
    }

    public function getCategory($id) { // /api/rpc/store/category/getcategory/id
        return DB::table('str_category_loc')
            ->join('str_category', 'str_category.id', '=', 'str_category_loc.ref_id')
            ->where('str_category.id', $id)
            ->get(array(
                'str_category.id',
                'str_category.name',
                'str_category_loc.name as altname',
                'str_category.game_id',
                'str_category.min_screenshots'
            ));
    }

    public function getCategoriesOfGame($id) { // /api/rpc/store/category/getcategoriesofgame/id
        return DB::table('str_category_loc')
            ->join('str_category', 'str_category.id', '=', 'str_category_loc.ref_id')
            ->join('str_games', 'str_category.game_id', '=', 'str_games.id')
            ->where('str_games.id', $id)
            ->get(array(
                'str_category.id',
                'str_category.name',
                'str_category_loc.name as altname'
            ));
    }

    public function getGameOfCategory($id) { // /api/rpc/store/category/getgameofcategory/id
        return DB::table('str_games_loc')
            ->join('str_games', 'str_games.id', '=', 'str_games_loc.ref_id')
            ->join('str_category', 'str_category.game_id', '=', 'str_games.id')
            ->where('str_category.id', $id)
            ->get(array(
                'str_games.id',
                'str_games.name',
                'str_games_loc.name as altname'
            ));
    }

    public function getCategoryGame($id) { // /api/rpc/store/category/getcategorygame/id
        return DB::table('str_category')
            ->select('game_id')
            ->where('id', $id)
            ->get();
    }

    public function getCategoryMinScreenshots($id) { // /api/rpc/store/category/getcategoryminscrot/id
        return DB::table('str_category')
            ->select('min_screenshots')
            ->where('id', $id)
            ->get();
    }

    public function getCategoryName($id) { // /api/rpc/store/category/getcategoryname/id
        return DB::table('str_category_loc')
            ->join('str_category', 'str_category.id', '=', 'str_category_loc.ref_id')
            ->where('str_category.id', $id)
            ->get(array(
                'str_category.name',
                'str_category_loc.name as altname'
            ));
    }

    public function getCategoryNameOfEntry($id) { // /api/rpc/store/category/getcategorynameofentry/id
        return DB::table('str_file')
            ->join('str_category', 'str_category.id', '=', 'str_file.cat_id')
            ->join('str_category_loc', 'str_category.id', '=', 'str_category_loc.ref_id')
            ->where('str_file.id', $id)
            ->get(array(
                'str_category.name',
                'str_category_loc.name as altname'
            ));
    }

    public function newCategory(Request $r) { // /api/rpc/store/category/newcategory
        $add = DB::table('str_category')
            ->insert([
                'name' => $r->name,
                'game_id' => $r->game_id,
                'min_screenshots' => $r->min_screenshots
            ]);

        return \Response::json($add);
    }

    public function editCategory(Request $r) { // /api/rpc/store/category/editcategory
        return DB::table('str_category')
            ->where('id', $r->id)
            ->update([
                'name' => $r->name,
                'min_screenshots' => $r->min_screenshots
            ]);
    }

    // Entries
    public function getAllEntries() { // /api/rpc/store/entry/getallentries
        return DB::table('str_file')
            ->select('*')
            ->get();
    }

    public function getAllApprovedEntries() { // /api/rpc/store/entry/getallapprovedentries
        return DB::table('str_file')
            ->select('*')
            ->where('isApproved', 1)
            ->get();
    }

    public function getAllBrokenEntries() { // /api/rpc/store/entry/getallbrokenentries
        return DB::table('str_file')
            ->select('*')
            ->where('isBroken', 1)
            ->get();
    }

    public function getAllPendingEntries() { // /api/rpc/store/entry/getallpendingentries
        return DB::table('str_file')
            ->select('*')
            ->where('isApproved', 0)
            ->get();
    }

    public function getNewEntries() { // /api/rpc/store/entry/getnewentries
        return DB::table('str_file')
            ->select(
                     'id',
                     'title',
                     'version',
                     'submit_date'
                    )
            ->where('isApproved', 1)
            ->orderBy('submit_date', 'desc')
            ->limit(5)
            ->get();
    }

    public function getHotEntries() { // /api/rpc/store/entry/gethotentries
        return DB::table('str_file')
            ->select(
                     'id',
                     'title',
                     'version',
                     'downloads'
                    )
            ->where('isApproved', 1)
            ->orderBy('downloads', 'desc')
            ->limit(5)
            ->get();
    }

    public function getEntriesPageAll($cat, $from, $to) { // /api/rpc/store/entry/getentriespageall/cat/from/to
        return DB::table('str_file')
            ->select(
                     'id',
                     'title',
                     'version',
                     'description',
                     'submit_date',
                     'last_date',
                     'views',
                     'downloads'
                    )
            ->where('cat_id', $cat)
            ->offset($from)
            ->limit($to)
            ->get();
    }

    public function getEntriesPageApproved($cat, $from, $to) { // /api/rpc/store/entry/getentriespageapproved/cat/from/to
        return DB::table('str_file')
            ->select(
                     'id',
                     'title',
                     'version',
                     'description',
                     'submit_date',
                     'last_date',
                     'views',
                     'downloads'
                    )
            ->where('cat_id', $cat)
            ->where('isApproved', 1)
            ->offset($from)
            ->limit($to)
            ->get();
    }

    public function getEntriesPagePopularView($cat, $from, $to) { // /api/rpc/store/entry/getentriespagepopularview/cat/from/to
        return DB::table('str_file')
            ->select(
                     'id',
                     'title',
                     'version',
                     'description',
                     'submit_date',
                     'last_date',
                     'views',
                     'downloads'
                    )
            ->where('cat_id', $cat)
            ->where('views', '>', 1000)
            ->offset($from)
            ->limit($to)
            ->get();
    }

    public function getEntriesPagePopularDownload($cat, $from, $to) { // /api/rpc/store/entry/getentriespagepopulardownload/cat/from/to
        return DB::table('str_file')
            ->select(
                     'id',
                     'title',
                     'version',
                     'description',
                     'submit_date',
                     'last_date',
                     'views',
                     'downloads'
                    )
            ->where('cat_id', $cat)
            ->where('downloads', '>', 1000)
            ->offset($from)
            ->limit($to)
            ->get();
    }

    public function getChangelog($id) { // /api/rpc/store/entry/getchangelog/id
        return DB::table('str_file')
            ->select('version', 'changelog')
            ->where('id', $id)
            ->get();
    }

    public function getNotice($id) { // /api/rpc/store/entry/getnotice/id
        return DB::table('str_file')
            ->select('title', 'version', 'warningnote')
            ->where('id', $id)
            ->get();
    }

    public function getDownloadCount($id) { // /api/rpc/store/entry/getdownloadcount/id
        return DB::table('str_file')
            ->select('downloads')
            ->where('id', $id)
            ->get();
    }

    public function updateDownloadCount(Request $r) { // /api/rpc/store/entry/updatedownloadcount
        return DB::table('str_file')
            ->where('id', $r->id)
            ->update(['downloads', $r->downloads]);
    }

    public function FileSizeConvert($bytes) {
        $bytes = floatval($bytes);
        $arBytes = array(
            0 => array(
                // "UNIT" => "TiB",
                // "VALUE" => pow(1024, 4)
                "UNIT" => "TQ",
                "VALUE" => pow(4096, 4)
                ),
            1 => array(
                // "UNIT" => "GiB",
                // "VALUE" => pow(1024, 3)
                "UNIT" => "GQ",
                "VALUE" => pow(4096, 3)
            ),
            2 => array(
                // "UNIT" => "MiB",
                // "VALUE" => pow(1024, 2)
                "UNIT" => "MQ",
                "VALUE" => pow(4096, 2)
            ),
            3 => array(
                // "UNIT" => "KiB",
                // "VALUE" => 1024
                "UNIT" => "KQ",
                "VALUE" => 4096
            ),
            4 => array(
                // "UNIT" => "B",
                "UNIT" => "Q",
                "VALUE" => 1
            )
        );

        foreach($arBytes as $arItem) {
            if($bytes >= $arItem["VALUE"]) {
                $result = $bytes / $arItem["VALUE"];
                $result = strval(round($result, 2))." ".$arItem["UNIT"];
                break;
            }
        }

        return $result;
    }

    public function getFilesOfEntry($id) { // /api/rpc/store/entry/getfilesofentry/id
        $files = array_map("htmlspecialchars", scandir("assets/store/$id"));
        $files = array_diff($files, array('..', '.', 'screens'));

        $result = array();

        foreach ($files as $file) {
            array_push($result, [
                'id' => $id,
                'file' => $file,
                'size' => $this->FileSizeConvert(filesize('assets/store/'.$id.'/'.$file))
            ]);
        }

        return $result;
    }

    public function getNextEntryId() { // /api/rpc/store/entry/getnextentryid
            $get = DB::table('str_file')->max('id');
            $get++;

            return $get;
    }

    public function getEntry($id, $mode) { // /api/rpc/store/entry/getentry/id/mode
        if ($mode == 'user') {
            return DB::table('str_owners')
                ->join('str_file', 'str_owners.file_id', '=', 'str_file.id')
                ->join('users', 'str_owners.user_id', '=', 'users.id')
                ->join('usr_details', 'usr_details.user_id', '=', 'str_owners.user_id')
                ->join('usr_profile', 'usr_profile.user_id', '=', 'str_owners.user_id')
                ->join('usr_perm_id', 'usr_perm_id.user_id', '=', 'str_owners.user_id')
                ->where('str_owners.user_id', $id)
                ->get(array(
                    'file_id',
                    'str_owners.user_id',
                    'cat_id',
                    'title',
                    'version',
                    'description',
                    'changelog',
                    'views',
                    'downloads',
                    'isApproved',
                    'submit_date',
                    'last_date',
                    'username',
                    'avatar',
                    'perm_id',
                    'gender',
                    'display_name',
                    'name_style',
                ));
        }
        else {
            return DB::table('str_owners')
                ->join('str_file', 'str_owners.file_id', '=', 'str_file.id')
                ->join('users', 'str_owners.user_id', '=', 'users.id')
                ->join('usr_details', 'usr_details.user_id', '=', 'str_owners.user_id')
                ->join('usr_profile', 'usr_profile.user_id', '=', 'str_owners.user_id')
                ->join('usr_perm_id', 'usr_perm_id.user_id', '=', 'str_owners.user_id')
                ->where('file_id', $id)
                ->take(1)
                ->get(array(
                    'file_id',
                    'str_owners.user_id',
                    'cat_id',
                    'title',
                    'version',
                    'description',
                    'changelog',
                    'views',
                    'downloads',
                    'isApproved',
                    'submit_date',
                    'last_date',
                    'username',
                    'avatar',
                    'perm_id',
                    'gender',
                    'display_name',
                    'name_style',
                ));
        }

    }

    public function getEntryName($id) { // /api/rpc/store/entry/getentryname/id
        return DB::table('str_file')
            ->select('title', 'version')
            ->where('id', $id)
            ->get();
    }

    public function getEntriesInCategory($cat_id) { // /api/rpc/store/entry/getentriesincategory/cat_id
        return DB::table('str_file')
            ->select('*')
            ->where('cat_id', $cat_id)
            ->get();
    }

    public function countEntriesInCategory($cat_id) { // /api/rpc/store/entry/countentriesincategory/cat_id
        // return $this->storePath.'/screens';
        return DB::table('str_file')
            ->where('cat_id', $cat_id)
            ->where('isApproved', 1)
            ->count();
    }

    public function countEntriesInCategoryFull($cat_id) { // /api/rpc/store/entry/countentriesincategoryfull/cat_id
        return DB::table('str_file')
            ->where('cat_id', $cat_id)
            ->count();
    }

    public function makedir(Request $r) {
        $id = $r->id;

        if (!mkdir($this->storePath.'/'.$id, 0755, true)) {
            Log::error('File MKDIR failed: ');
            exit();
        }

        if (!mkdir($this->storePath.'/'.$id.'/screens', 0755, true)) {
            Log::error('Asset MKDIR failed: ');
            exit();
        }
    }

    public function uploadEntry(Request $r) { // /api/rpc/store/entry/upload
        header('Access-Control-Allow-Origin: *');
        $id = $r->id;

        Log::info('Name: '.$r->file('imgfile')); //TMP
        Log::info('Type: '.gettype($r->file('imgfile'))); // TMP

        $r->file('upfile')->move(public_path('storage/store'.$id), $r->file('imgfile')->getClientOriginalName);
        $r->file('imgfile')->move(public_path('storage/store'.$id.'/screens'), $r->file('imgfile')->getClientOriginalName);

        exit(); // TMP

        $add = DB::table('str_file')
            ->insert([
                'game_id' => intval($r->game_id),
                'cat_id' => intval($r->cat_id),
                'title' => $r->title,
                'version' => $r->version,
                'video' => (!empty($r->video) ? $r->video : ''),
                'description' => $r->description,
                'changelog' => '',
                'warningnote' => (!empty($r->warningnote) ? $r->warningnote : ''),
                'submit_date' => intval($r->submit_date),
                'last_date' => intval(0),
                'views' => intval(0),
                'downloads' => intval(0),
                'isApproved' => intval(1),
                'isBroken' => intval(0),
                'failreason' => '',
                'breakreason' => '',
                'approveignore' => intval(0),
                'brokenignore' => intval(0)
            ]);

        return \Response::json($add);
    }

    public function updateEntry(Request $r) { // /api/rpc/store/entry/update
        return DB::table('str_file')
            ->where('id', $r->id)
            ->update([
                'cat_id' => $r->cat_id,
                'title' => $r->title,
                'version' => $r->version,
                'description' => $r->description,
                'changelog' => $r->changelog,
                'warningnote' => $r->warningnote,
                'last_date' => $r->last_date
            ]);
    }

    public function restoreEntry(Request $r) { // /api/rpc/store/entry/restore
        return DB::table('str_file')
            ->where('id', $r->id)
            ->update(['isApproved' => 1]);
    }

    public function removeEntry(Request $r) { // /api/rpc/store/entry/remove
        return DB::table('str_file')
            ->where('id', $r->id)
            ->update(['isApproved' => 0]);
    }

    public function browsePermissions($uid) {
        // Get user ID.
        $perm = $this->objUser->getUser($uid);

        // Does the user ID exist? Grand the appropriate rights. Otherwise, use guest.
        if ($uid != 0) {
            // Store permissions.
            $grouppermstr = $this->objPermission->getPermissionGroup('str', $perm[0]->perm_id);
            $userpermstr = $this->objPermission->getPermissionUser('str', $uid);

            // User permissions.
            $grouppermusr = $this->objPermission->getPermissionGroup('usr', $perm[0]->perm_id);
            $userpermusr = $this->objPermission->getPermissionUser('usr', $uid);

            // Now provide an array of user overwritten permissions if it exists. Otherwise, give its group permissions.
            $strarr = array();
            $usrarr = array();

            if (!empty($userpermstr[0])) {
                $strarr = (array)$userpermstr[0];
            }
            else {
                $strarr = (array)$grouppermstr[0];
            }

            if (!empty($userpermusr[0])) {
                $usrarr = (array)$userpermusr[0];
            }
            else {
                $usrarr = (array)$grouppermusr[0];
            }

            $merge = array();
            $merge = array_merge($strarr, $usrarr);

            return $merge;
        }
        else {
            // Store permissions.
            $grouppermstr = $this->objPermission->getPermissionGroup('str', 6);

            // User permissions.
            $grouppermusr = $this->objPermission->getPermissionGroup('usr', 6);

            // Since guests don't have user overwritten permissions, simply return the group permissions.
            $merge = array();
            $merge = array_merge((array)$grouppermstr[0], (array)$grouppermusr[0]);

            return $merge;
        }
    }

}
