<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;

use App\Classes\FTN\Packet;
use App\Models\{Address,Domain,Setup};

class HomeController extends Controller
{
	public function network(Domain $o)
	{
		if (! $o->public && ! Gate::check('admin',$o))
			abort(404);

		$o->load(['zones.system','zones.domain']);

		return view('domain.view')
			->with('o',$o);
	}

	/**
	 * Render a view that summarises the users permissions
	 */
	public function permissions()
	{
		return view('auth.permissions')
			->with('user',Auth::user());
	}

	/**
	 * Show a packet dump
	 *
	 * @param Request $request
	 * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
	 */
	public function pkt(Request $request)
	{
		$pkt = NULL;
		$file = NULL;

		if ($request->post()) {
			$request->validate([
				'file' => 'required|filled|min:1',
			]);

			foreach ($request->allFiles() as $key => $filegroup) {
				if ($key !== 'file')
					continue;

				foreach ($filegroup as $file) {
					try {
						$pkt = Packet::open($file);

					} catch (\Exception $e) {
						return redirect()->back()->withErrors(sprintf('%s (%s:%d)',$e->getMessage(),$e->getFile(),$e->getLine()));
					}

					break;
				}
			}
		}

		return view('pkt')
			->with('file',$file)
			->with('result',$pkt)
			->with('hexdump',$file ? hex_dump(file_get_contents($file)) : '');
	}

	/**
	 * Process searching
	 *
	 * @param Request $request
	 * @return Collection
	 */
	public function search(Request $request): Collection
	{
		$this->middleware('auth');

		$result = collect();

		list($zone_id,$host_id,$node_id,$point_id,$domain) = sscanf($request->query('term'),'%d:%d/%d.%d@%s');

		# Look for Opportunities
		foreach (Address::select(['systems.name',DB::raw('systems.id AS system_id'),'zones.zone_id','region_id','host_id','node_id','point_id'])
			->join('zones',['zones.id'=>'addresses.zone_id'])
			->rightjoin('systems',['systems.id'=>'addresses.system_id'])
			->when($zone_id || $host_id || $node_id,function($query) use ($zone_id,$host_id,$node_id) {
				return $query
					->when($zone_id,function($q,$zone_id) { return $q->where('zones.zone_id',$zone_id); })
					->where(function($q) use ($host_id) {
						return $q
							->when($host_id,function($q,$host_id) { return $q->where('region_id',$host_id); })
							->when($host_id,function($q,$host_id) { return $q->orWhere('host_id',$host_id); });
					})
					->when($node_id,function($q,$node_id) { return $q->where('node_id','ilike','%'.$node_id.'%'); });
			})
			->orWhere('systems.name','ilike','%'.$request->query('term').'%')
			->orWhere('systems.sysop','ilike','%'.$request->query('term').'%')
			->OrderBy('systems.name')
			->get() as $o)
		{
			$ftn = NULL;

			if ($o->zone_id && ($o->region_id||$o->host_id) && is_numeric($o->node_id) && is_numeric($o->point_id))
				$ftn = sprintf('%d:%d/%d.%d',$o->zone_id,$o->host_id ?: $o->region_id,$o->node_id,$o->point_id);

			$result->push(['id'=>$o->system_id,'name'=>$o->name.($ftn ? ' '.$ftn : ''),'value'=>url('ftn/system/addedit',[$o->system_id]),'category'=>'Systems']);
		}

		return $result->unique(['id'])->take(10)->values();
	}

	/**
	 * System Setup
	 *
	 * @note: Protected by Route
	 */
	public function setup(Request $request)
	{
		$o = Setup::findOrNew(config('app.id'));

		if ($request->post()) {
			$request->validate([
				'system_id' => 'required|exists:systems,id',
				'binkp' => 'nullable|array',
				'binkp.*' => 'nullable|numeric',
				'options' => 'nullable|array',
				'options.*' => 'nullable|numeric',
			]);

			if (! $o->exists) {
				$o->id = config('app.id');
				$o->zmodem = 0;
				$o->emsi_protocols = 0;
				$o->protocols = 0;
				$o->permissions = 0;
			}

			$o->binkp = collect($request->post('binkp'))->sum();
			$o->options = collect($request->post('options'))->sum();
			$o->system_id = $request->post('system_id');
			$o->save();
		}

		return view('setup')
			->with('o',$o);
	}
}