<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Recipe;
use App\RecipeIngredient;
use App\RecipeCategory;
use App\User;

class RecipeController extends Controller
{
  /**
   * Enforce middleware
   */
  public function __construct(){
    $this->middleware('auth', ['except' => ['index','show']]);
  }
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index()
  {
    $recipes = Recipe::with('user')->get();
    $categories=array_values(RecipeCategory::get()->sortby('name')->pluck('name')->unique()->toArray());
    return view('recipes.index')->with('recipes', $recipes)->with('categories',$categories);
  }

  public function show($id)
  {
    $recipe=Recipe::with('user')->findOrFail($id);
    return view('recipes.show')->with('recipe', $recipe);
  }

  public function edit($id){
    //verify user has permission to access page
    $recipe=Recipe::with('user')->with('categories')->with('ingredients')->findOrFail($id);
    if(!(\Auth::user()->hasPerm('EditRecipe') || \Auth::user()->id == $recipe->user_id)){
      return redirect()->route('recipes.index')->with('message','You don\'t have permission to access this page');
    }

    $lists['ingredients']=array_values(RecipeIngredient::get()->sortby('name')->pluck('name')->unique()->toArray());
    $lists['measurements']=array_values(RecipeIngredient::get()->sortby('measurement')->pluck('measurement')->unique()->toArray());
    $lists['categories']=array_values(RecipeCategory::get()->sortby('name')->pluck('name')->unique()->toArray());
    $lists['authors']=array_values(Recipe::get()->sortby('author')->pluck('author')->unique()->toArray());
    $lists['owners']=User::select('id','name')->get()->sortby('name');
    return view('recipes.edit')->with('recipe', $recipe)->with('lists',$lists);
  }

  public function update(Request $request, $id)
  {
    //verify user has permission to access page
    $recipe = Recipe::with('ingredients')->with('categories')->findOrFail($id);
    if(!(\Auth::user()->hasPerm('EditRecipe') || \Auth::user()->id == $recipe->user_id)){
      return redirect()->route('recipes.index')->with('message','You don\'t have permission to access this page');
    }

    $this->validate($request, [
      'name'=>'required|max:500',
      'author'=>'required|max:500',
      'user_id'=>'required',
      'servings'=>'required|integer',
      'serving_size'=>'required|max:40',
      'description'=>'max:5000',
      'instructions'=>'required|max:5000'
    ]);

    //break categories and ingredients into arrays for validation
    $categories = array();
    $ingredients = array();
    foreach($request->all() as $element => $value){
      if(preg_match('/category_.*/', $element)){
        $explosion = explode('_',$element);
        $categories[$explosion[1]][$explosion[2]]=$value;
      }else if(preg_match('/ingredient_.*/', $element)){
        $explosion = explode('_',$element);
        $ingredients[$explosion[1]][$explosion[2]]=$value;
      }
    }

    foreach($categories as $category){
      $newreq = new Request($category);
      $this->validate($newreq, [
        'name'=>'required|max:50',
      ]);
    }

    foreach($ingredients as $index => $ingredient){
      $newreq = new Request($ingredient);
      $this->validate($newreq, [
        'order'=>'required|integer',
        'quantity'=>['required','regex:/(^\d+\/\d+$)|(^\d*\.\d+$)|(^\d+ \d\/\d$)|(^\d+$)/i'],
        'measurement'=>'required|max:40',
        'name'=>'required|max:500',
        'notes'=>'max:500'
      ]);
      if ($ingredient['notes'] == null){
        $ingredients[$index]['special_notes'] = '';
      }else{
        $ingredients[$index]['special_notes'] = $ingredient['notes'];
      }
      if(array_key_exists('alternative', $ingredient) && $ingredient['alternative'] == 'on'){
        $ingredients[$index]['alternative'] = true;
      }else{
        $ingredients[$index]['alternative'] = false;
      }
    }

    $update = $request->only('name','author','user_id','servings','serving_size','last_modified','description','instructions');
    $update['last_modified']=now();
    $recipe->fill($update)->save();

    //Delete categories that don't exist in new category array
    foreach($recipe->categories as $category){
      if(!array_key_exists($category->id,$categories)){
        $category->delete();
      }
    }

    //Delete ingredients that don't exist in new ingredient array
    foreach($recipe->ingredients as $ingredient){
      if(!array_key_exists($ingredient->id,$ingredients)){
        $ingredient->delete();
      }
    }

    //create/update categories
    foreach($categories as $categoryid => $category){
      //Add recipe_id
      $category["recipe_id"]=$id;
      $newreq = new Request($category);
      //Find category if exists, create if it doesn't
      $currentcategory = RecipeCategory::where('id','=',$categoryid)->first();
      if($currentcategory === null){
        RecipeCategory::create($newreq->only('recipe_id','name'));
      }else{
        $update = $newreq->only('recipe_id','name');
        $currentcategory->fill($update)->save();
      }
    }

    //create/update ingredients
    foreach($ingredients as $ingredientid => $ingredient){
      //Add recipe_id
      $ingredient["recipe_id"]=$id;
      $newreq = new Request($ingredient);
      //Find category if exists, create if it doesn't
      $currentingredient = RecipeIngredient::where('id','=',$ingredientid)->first();
      if($currentingredient === null){
        RecipeIngredient::create($newreq->only('recipe_id','order','alternative','quantity','measurement','name','special_notes'));
      }else{
        $update = $newreq->only('recipe_id','order','alternative','quantity','measurement','name','special_notes');
        $currentingredient->fill($update)->save();
      }
    }
    return redirect()->route('recipes.index')->with('message','Recipe successfully edited.');
  }

  public function create(){
    $lists['ingredients']=array_values(RecipeIngredient::get()->sortby('name')->pluck('name')->unique()->toArray());
    $lists['measurements']=array_values(RecipeIngredient::get()->sortby('measurement')->pluck('measurement')->unique()->toArray());
    $lists['categories']=array_values(RecipeCategory::get()->sortby('name')->pluck('name')->unique()->toArray());
    $lists['authors']=array_values(Recipe::get()->sortby('author')->pluck('author')->unique()->toArray());
    $lists['owners']=User::select('id','name')->get()->sortby('name');
    return view('recipes.create')->with('lists',$lists);
  }

  public function store(Request $request){

    $this->validate($request, [
      'author'=>'required|max:500',
      'user_id'=>'required',
      'servings'=>'required|integer',
      'serving_size'=>'required|max:40',
      'description'=>'max:5000',
      'instructions'=>'required|max:5000'
    ]);

    //break categories and ingredients into arrays for validation
    $categories = array();
    $ingredients = array();
    foreach($request->all() as $element => $value){
      if(preg_match('/category_.*/', $element)){
        $explosion = explode('_',$element);
        $categories[$explosion[1]][$explosion[2]]=$value;
      }else if(preg_match('/ingredient_.*/', $element)){
        $explosion = explode('_',$element);
        $ingredients[$explosion[1]][$explosion[2]]=$value;
      }
    }

    foreach($categories as $category){
      $newreq = new Request($category);
      $this->validate($newreq, [
        'name'=>'required|max:50',
      ]);
    }

    foreach($ingredients as $index => $ingredient){
      $newreq = new Request($ingredient);
      $this->validate($newreq, [
        'order'=>'required|integer',
        'quantity'=>['required','regex:/(^\d+\/\d+$)|(^\d*\.\d+$)|(^\d+ \d\/\d$)|(^\d+$)/i'],
        'measurement'=>'required|max:40',
        'name'=>'required|max:500',
        'notes'=>'max:500'
      ]);
      if ($ingredient['notes'] == null){
        $ingredients[$index]['special_notes'] = '';
      }else{
        $ingredients[$index]['special_notes'] = $ingredient['notes'];
      }
      if(array_key_exists('alternative', $ingredient) && $ingredient['alternative'] == 'on'){
        $ingredients[$index]['alternative'] = true;
      }else{
        $ingredients[$index]['alternative'] = false;
      }
    }

    $create=$request->only('author','user_id','servings','serving_size','name','description','instructions');
    $create['date_entered']=now();
    $create['date_modified']=now();
    $recipe = Recipe::create($create);

    //create categories
    foreach($categories as $categoryid => $category){
      //Add recipe_id
      $category["recipe_id"]=$recipe->id;
      $newreq = new Request($category);
      RecipeCategory::create($newreq->only('recipe_id','name'));
    }

    //create ingredients
    foreach($ingredients as $ingredientid => $ingredient){
      //Add recipe_id
      $ingredient["recipe_id"]=$recipe->id;
      $newreq = new Request($ingredient);
      RecipeIngredient::create($newreq->only('recipe_id','order','alternative','quantity','measurement','name','special_notes'));
    }
    return redirect()->route('recipes.index')->with('message','Recipe successfully edited.');
  }

  /**
   * Remove the specified resource from storage.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function destroy($id)
  {
    //Find and remove user
    $recipe = Recipe::with('categories')->with("ingredients")->findOrFail($id);
    if(!(\Auth::user()->hasPerm('DeleteRecipe') || \Auth::user()->id == $recipe->user_id)){
      return redirect()->route('recipes.index')->with('message','You don\'t have permission to access this page');
    }
    foreach($recipe->categories as $c) $c->delete();
    foreach($recipe->ingredients as $i) $i->delete();
    $recipe->delete();

    return redirect()->route('recipes.index')->with('message','Recipe successfully deleted.');
  }
}