<?php

namespace App\Http\Controllers;

use App\Vector;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

class VectorsController extends Controller
{
  /**
   * @apiDefine Header
   * @apiHeader {String} Authorization Bearer + token
   * @apiHeaderExample Authorization header example
   * Authorization: Bearer eyJ0eXAiO.iJKV1QiLCJhb.GciOiJIUzI1NiJ9
   */

   /**
    * @apiDefine JWTErrors
    * @apiError TokenNotProvided Token not provided.
    * @apiErrorExample TokenNotProvided response:
    *     HTTP/1.1 401 Unauthorized
    *     {
    *       "error": "Token not provided."
    *     }
    *
    * @apiError ExpiredToken Provided token is expired.
    * @apiErrorExample ExpiredToken response:
    *     HTTP/1.1 400 Bad Request
    *     {
    *       "error": "Provided token is expired."
    *     }
    *
    * @apiError DecodingError An error while decoding token.
    * @apiErrorExample DecodingError response:
    *     HTTP/1.1 400 Bad Request
    *     {
    *       "error": "An error while decoding token."
    *     }
    */

    /**
     * @api {get} /vectors Get All Vector Layers
     * @apiVersion 1.0.0
     * @apiName GetAllVectors
     * @apiGroup VectorLayer
     *
     * @apiSuccess {Array} empty Array of vector layers.
     *
     * @apiSuccessExample Success Response:
     *     HTTP/1.1 200 OK
     *     [
     *       {
     *         "id": 1,
     *         "zoom_level": 17,
     *         "filepath": "vectors/Vyskum.json",
     *         "color": "#ffcd56"
     *       },
     *       {
     *         "id": 2,
     *         "zoom_level": 19,
     *         "filepath": "vectors/Dvorce.json",
     *         "color": "#6ecc39"
     *       }
     *     ]
     */
    public function getAll()
    {
        return response()->json(Vector::all());
    }

    /**
      * @api {get} /vectors/:id Get Vectors Layer Details
      * @apiVersion 1.0.0
      * @apiName GetVectorLayerDetails
      * @apiGroup VectorLayer
      *
      * @apiParam {Number} id Vectors layer unique ID.
      *
      * @apiSuccess {Number} id ID of the vector layer.
      * @apiSuccess {Number} zoom_level Maps zoom level on which layer should be visible.
      * @apiSuccess {String} filepath Filepath of save JSON file.
      * @apiSuccess {String} color Color of vector layer.
      *
      * @apiSuccessExample Success Response:
      *     HTTP/1.1 200 OK
      *     {
      *       "id": 1,
      *       "zoom_level": 17,
      *       "filepath": "vectors/Vyskum.json",
      *       "color": "#ffcd56"
      *     }
      *
      * @apiError VectorLayerNotFound Vector layer with provided id doesn't exists!
      *
      * @apiErrorExample Error Response:
      *     HTTP/1.1 404 Not Found
      *     {
      *       "error": "VectorLayerNotFound"
      *     }
      */
    public function getLayerDetails($id)
    {
      $vectorDetails = Vector::where('vectors.id', $id)->select('id', 'zoom_level', 'filepath', 'color')->first();

      if (!$vectorDetails) {
        return response()->json(["error" => "Vector layer with provided id doesn't exists!"], 404);
      }

      return response()->json([
          'id' => $vectorDetails->id,
          'zoom_level' => $vectorDetails->zoom_level,
          'filepath' => $vectorDetails->filepath,
          'color' => $vectorDetails->color
        ], 200)->setEncodingOptions(JSON_NUMERIC_CHECK);
    }

    /**
      * @api {get} /vectors/data/:id Get Vectors Layer Data
      * @apiVersion 1.0.0
      * @apiName GetVectorLayerData
      * @apiGroup VectorLayer
      *
      * @apiParam {Number} id Vectors layer unique ID.
      *
      * @apiSuccessExample Success Response:
      *     HTTP/1.1 200 OK
      *      {
      *        "type": "FeatureCollection",
      *        "crs": {
      *          "type": "name"
      *        },
      *        "features": [
      *          {
      *            "type": "Feature",
      *            "id": 0,
      *            "geometry": {
      *              "type": "Polygon",
      *              "coordinates": [
      *                [
      *                  [
      *                    16.8969958,
      *                    48.7320973
      *                  ],
      *                  [
      *                    16.8970657,
      *                    48.7320529
      *                  ],
      *                  [
      *                    16.8971048,
      *                    48.7320789
      *                  ]
      *                ]
      *              ]
      *            }
      *          },
      *          {
      *            "type": "Feature",
      *            "id": 1,
      *            "geometry": {
      *              "type": "Polygon",
      *              "coordinates": [
      *                [
      *                  [
      *                    16.8969958,
      *                    48.7320973
      *                  ],
      *                  [
      *                    16.8969351,
      *                    48.7320584
      *                  ]
      *                ]
      *              ]
      *            }
      *          }
      *        ]
      *      }
      *
      * @apiErrorExample Error Response:
      *     HTTP/1.1 404 Not Found
      */
    public function getLayerData($id)
    {
        $layer = Vector::findOrFail($id);
        return response()->download(Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix($layer->filepath));
    }

    /**
     * @api {post} /vectors Create New Vector Layer
     * @apiVersion 1.0.0
     * @apiName CreateNewVectorLayer
     * @apiGroup VectorLayer
     * @apiPermission authenticated
     *
     * @apiUse Header
     *
     * @apiParam {Number} zoom_level Markers latitude.
     * @apiParam {String{..50}} filename Name of JSON file being uploaded.
     * @apiParam {String{..5000000}} geojson Content of JSON which will be saved as provided name.
     * @apiParam {String{..10}} color Color of vector layer.
     *
     * @apiSuccess {String} success Success message.
     *
     * @apiSuccessExample Success Response:
     *     HTTP/1.1 200 OK
     *     {
     *       "success": "GeoJSON was successfully uploaded."
     *     }
     *
     * @apiUse JWTErrors
     */
    public function create(Request $request)
    {
      //validation rules
      $rules = [
        'zoom_level' => 'required|numeric',
        'filename' => 'required|max:50',
        'geojson' => 'required|max:5000000',
        'color' => 'required|max:10'
      ];

      //validate request
      $this->validate($request, $rules);

      //save file
      $path = $request->geojson->storeAs('vector_layers', $request->filename);

      $layer = Vector::create([
          'zoom_level' => $request->zoom_level,
          'filepath' => $path,
          'color' => $request->color
      ]);

      return response()->json(['success' => 'GeoJSON was successfully uploaded.'], 200);
    }

    /**
     * @api {post} /vectors/:id Update Vector Layer
     * @apiVersion 1.0.0
     * @apiName UpdateVectorLayer
     * @apiGroup VectorLayer
     * @apiPermission authenticated
     *
     * @apiUse Header
     *
     * @apiParam {Number} id Vectors layer unique ID.
     *
     * @apiParam {Number} zoom_level Markers latitude.
     * @apiParam {String{..50}} filename Name of JSON file being uploaded.
     * @apiParam {String{..5000000}} geojson Content of JSON which will be saved as provided name.
     * @apiParam {String{..10}} color Color of vector layer.
     *
     * @apiSuccess {String} success Success message.
     *
     * @apiSuccessExample Success Response:
     *     HTTP/1.1 200 OK
     *     {
     *       "success": "GeoJSON layer was successfully updated."
     *     }
     *
     * @apiUse JWTErrors
     */
    public function update($id, Request $request)
    {
      //validation rules
      $rules = [
        'zoom_level' => 'required|numeric',
        'filename' => 'max:50',
        'geojson' => 'max:5000000',
        'color' => 'required|max:10'
      ];

      //validate request
      $this->validate($request, $rules);

      $vectorLayer = Vector::findOrFail($id);

      if (!$request->has('filename') || $request->filename == "" ) {
        $vectorLayer->zoom_level = $request->zoom_level;
        $vectorLayer->color = $request->color;
        $vectorLayer->save();

        return response()->json(['success' => 'GeoJSON layer was successfully updated.'], 200);
      } else {
        //delete files from disk
        Storage::delete('/'.$vectorLayer->filepath);
        //save file
        $path = $request->geojson->storeAs('vector_layers', $request->filename);
        $vectorLayer->update([
          'zoom_level' => $request->zoom_level,
          'filepath' => $path,
          'color' => $request->color
        ]);
      }

      return response()->json(['success' => 'GeoJSON layer was successfully updated.'], 200);
    }

    /**
     * @api {delete} /vectors/:id Delete Vector Layer
     * @apiVersion 1.0.0
     * @apiName DeleteVectorLayer
     * @apiGroup VectorLayer
     * @apiPermission authenticated
     *
     * @apiUse Header
     *
     * @apiParam {Number} id Vectors layer unique ID.
     *
     * @apiSuccess {String} success Success message.
     *
     * @apiSuccessExample Success Response:
     *     HTTP/1.1 202 OK
     *     {
     *       "success": "GeoJSON layer was successfully deleted."
     *     }
     *
     * @apiUse JWTErrors
     */
    public function delete($id)
    {
        $layer = Vector::findOrFail($id);
        $filepath = $layer->filepath;

        $layer->delete();

        //delete GeoJSON file from disk
        Storage::delete('/'.$filepath);

        return response()->json(["success" => "GeoJSON layer was successfully deleted."], 202);
    }
}
