<?php

namespace App\Http\Controllers;

use App\Http\ViewHelpers\ViewFeeder;
use App\Location;
use App\Permission;
use Carbon\Carbon;
use DB;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Lang;
use Redirect;
use Session;

/**
 * Class LocationController
 * @package App\Http\Controllers
 */
class LocationController extends Controller implements ViewFeederAwareController
{
    const COLUMNS = [
        'id',
        'name',
        //'room',
        'created_at',
        'updated_at'
    ];

    /**
     * Create a new controller instance.
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Display a listing of the resource.
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $this->validate($request, [
            'sort' => Rule::in(self::COLUMNS),
            'ordering' => 'in:asc,desc',
            'count' => 'integer|min:5|max:100'
        ]);

        $sort = $request->get('sort', 'name');
        $ordering = $request->get('ordering', 'asc');
        $count = intval($request->get('count', 10));;

        $possibleFilters = ['name', 'room'];
        $where = [];

        foreach ($possibleFilters as $possibleFilter) {
            $filter = $request->get($possibleFilter, null);
            if ($filter) {
                $where[] = [$possibleFilter, 'LIKE', str_replace('*', '%', $filter)];
            }
        }

        $entityClasses = DB::table('locations as l')
            ->select([
                'l.id as id',
                'l.name as name',
                'l.room as room',
                'l.created_at as created_at',
                'l.updated_at as updated_at'
            ])
            ->where($where)
            ->orderBy($sort, $ordering)
            ->orderBy('id', 'desc')
            ->paginate($count);

        $viewFeeder = new ViewFeeder($this, ViewFeeder::LIST);

        return view('results.list', $viewFeeder
            ->results($entityClasses)
            ->sorting($sort, $ordering)
            ->permissions([
                'canEdit' => Permission::EDIT_LOCATION,
                'canDelete' => Permission::DELETE_LOCATION
            ])
            ->size(7)
            ->feed()
        );
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $viewFeeder = new ViewFeeder($this, ViewFeeder::CREATE);

        return view('non-device.create', $viewFeeder->feed());
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store(Request $request)
    {
        $this->validate($request, [
            'name' => 'bail|required|unique:locations|max:255'
        ]);

        $location = new Location([
            'name' => $request->name
        ]);

        $location->save();

        Session::flash('success', Lang::get('location.create_success'));

        return Redirect::route(self::getRouterName() . '.show', $location->id);
    }

    /**
     * Display the specified resource.
     *
     * @param Location $location
     * @return \Illuminate\Http\Response
     * @internal param int $id
     */
    public function show(Location $location)
    {
        $viewFeeder = new ViewFeeder($this, ViewFeeder::SHOW);

        $location->children_ids = DB::table('locations as l')
            ->where('l.id', '=', $location->id)
            ->join('entities as d', 'l.id', '=', 'd.location_id')
            ->join('entity_classes as dc', 'd.entity_class_id', '=', 'dc.id')
            ->select([
                'dc.id as class_id',
                'dc.name as class_name',
                'dc.is_type as is_type',
                DB::raw('COUNT(*) as entities_count')
            ])
            ->groupBy('dc.id')
            ->get();

        return view('non-device.show', $viewFeeder
            ->result($location)
            ->permissions([
                'canEdit' => Permission::EDIT_LOCATION,
                'canDelete' => Permission::DELETE_LOCATION
            ])
            ->size(6)
            ->feed());
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param Location $location
     * @return \Illuminate\Http\Response
     * @internal param int $id
     */
    public function edit(Location $location)
    {
        $viewFeeder = new ViewFeeder($this, ViewFeeder::EDIT);

        return view('non-device.edit', $viewFeeder
            ->result($location)
            ->size(6)
            ->feed());
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request $request
     * @param Location $location
     * @return \Illuminate\Http\RedirectResponse
     * @internal param int $id
     */
    public function update(Request $request, Location $location)
    {
        if ($location->name === $request->get('name')) {
            Session::flash('error', Lang::get('validation.unchanged'));
            return Redirect::back();
        }

        if ($request->has('id')) {
            Session::flash('error', Lang::get('validation.id_change_forbidden'));
            return Redirect::back();
        }

        $this->validate($request, [
            'name' => 'bail|required|unique:locations|max:255'
        ]);

        $location->name = $request->name;

        $location->updated_at = Carbon::now();
        $location->save();

        Session::flash('success', Lang::get('location.update_success'));

        return Redirect::route(self::getRouterName() . '.show', $location->id);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param Location $location
     * @return \Illuminate\Http\RedirectResponse
     * @internal param int $id
     */
    public function destroy(Location $location)
    {
        $deleted = $location->delete();

        if ($deleted)
            Session::flash('success', Lang::trans('location.delete_success', ['id' => $location->id]));
        else
            Session::flash('error', Lang::trans('location.delete_failed', ['id' => $location->id]));

        return Redirect::route(self::getRouterName() . '.index');
    }

    /**
     * Gets the name of the router to be used from the view.
     *
     * @return string
     */
    public static function getRouterName(): string
    {
        return 'locations';
    }

    /**
     * Returns singular of object controller is working with.
     *
     * @return string
     */
    public function getSingular(): string
    {
        return 'Location';
    }

    /**
     * Returns plural of object controller is working with.
     *
     * @return string
     */
    public function getPlural(): string
    {
        return 'Locations';
    }

    /**
     * Returns array of columns to be shown when listing objects controller is working with.
     *
     * @return array
     */
    public function getColumns(): array
    {
        return self::COLUMNS;
    }
}
