<?php

  class SubmissionController extends Controller
  {

    public function __construct()
    {
      $this->beforeFilter('csrf', ['on' => 'post']);
    }

    public function getIndex()
    {
      App::abort('404');
    }

    public function postCheckEmail()
    {
      $response = [
        "success" => TRUE,
        "result"  => ""
      ];

      $data = [
        'email' => Input::get('email')
      ];

      $rules = [];
      $rules['email'] = 'required|max:100|email|unique:users';

      $validator = Validator::make(
        $data,
        $rules
      );

      if ($validator->fails()) {
        $response['success'] = FALSE;
        $response['result'] = $validator->messages();
      }

      return Response::json($response, 200);

    }

    public function postSubmit()
    {
      $response = [
        "success" => TRUE,
        "result"  => "Success"
      ];

      $data = [
        'email'         => Input::get('email'),
        'originalImage' => Input::file('image'),
        'treatedImage'  => Input::file('image_treated'),
        'terms'         => Input::get('terms')
      ];

      $rules = [
        'email'         => 'required|max:100|email',
        'originalImage' => 'required|image|max:' . Config::get('project/media.allowedSize.image') . '',
        'treatedImage'  => 'required|image|max:' . Config::get('project/media.allowedSize.image') . '',
        'terms'         => 'required|accepted'
      ];

      $validator = Validator::make(
        $data,
        $rules
      );

      if ($validator->fails()) {
        $response['success'] = FALSE;
        $response['result'] = $validator->messages();

        return Response::json($response, 200);
      }


      DB::beginTransaction();
      try {

        $user = $this->_checkUserExists($data['email']);

        if (!$user) {
          $user = $this->_createUser($data['email']);
        }

        if ($user) {
          if ($user->submissions()->count() > 0) {
            $response['success'] = FALSE;
            $response['result'] = "User already submitted";

            return Response::json($response, 200);
          }
        }

        $originalImage = $this->_addImageToBo($data['originalImage'], 'submission');
        $treatedImage = $this->_addImageToBo($data['treatedImage'], 'submission_treated', $user);

        if (!$originalImage) {

          Log::error("=== IMAGE ERROR ===");
          Log::error($originalImage);
          Log::error("=== IMAGE ERROR ===");
          $response['success'] = FALSE;
          $response['result'] = 'Failed adding original image';

          return Response::json($response, 200);
        }

        if (!$treatedImage) {
          $response['success'] = FALSE;
          $response['result'] = 'Failed adding treated image';

          return Response::json($response, 200);
        }

        $this->_createSubmission($user, $originalImage, $treatedImage);

        // Send Tracking Info to Client
        $trackingHash = $user->tracking->hash;
        $utmCampaign = Config::get('project/tracking.utmCampaign');

        $shareUrl = lang_url('/', getActiveLanguage()) . '?utm_content=' . $trackingHash;
        $seeYourImageUrl = lang_url('/', getActiveLanguage()) . '?user_image=' . $trackingHash;
        $onlineVersionUrl = lang_url('/email' . '?user_email=' . $user->email);
        $optOutLink = lang_url(Lang::get('routes.uri_opt_out') . '?user_email=' . $user->email);

        $bitlyFacebook = $user->tracking->bitly_facebook;
        $bitlyTwitter = $user->tracking->bitly_twitter;
        $bitlyPinterest = $user->tracking->bitly_pinterest;

        $resultImage = getMediaUrl($treatedImage->filename);
        DB::commit();
        Log::info($originalImage);
      } catch (Exception $e) {
        DB::rollback();
        Log::error($e);
        $response['success'] = FALSE;
        $response['result'] = 'Something went sideways.';

        return Response::json($response, 200);
      }

      $response['result'] = [
        "shareUrl"        => $shareUrl,
        "image"           => $resultImage,
        "seeYourImageUrl" => $seeYourImageUrl,
        'shareFacebook'   => $bitlyFacebook,
        'shareTwitter'    => $bitlyTwitter,
        'sharePinterest'  => $bitlyPinterest
      ];

      GalleryService::updateActivityCounter(1);
      EmailerService::sendConfirmation($user->email, $shareUrl, $resultImage, $onlineVersionUrl, $optOutLink, $seeYourImageUrl);

      return Response::json($response, 200);
    }

    public function postDonate()
    {
      $response = [
        "success" => TRUE,
        "result"  => "Success"
      ];

      $data = [
        'email'           => Input::get('email'),
        'donation_amount' => Input::get('donation_amount')
      ];

      $rules = [
        'email'           => 'required|max:100|email',
        'donation_amount' => 'required'
      ];

      $validator = Validator::make(
        $data,
        $rules
      );

      if ($validator->fails()) {
        $response['success'] = FALSE;
        $response['result'] = $validator->messages();

        return Response::json($response, 200);
      }

      $user = $this->_checkUserExists($data['email']);

      if (!$user) {
        $user = $this->_createUser($data['email']);
      }

      $this->_createDonation($user, $data['donation_amount']);

      return Response::json($response, 200);

    }

    public function postImage()
    {
      $imageFile = Input::file('image');

      $moveToTemp = $this->_addImageTempFolder($imageFile);

      if (!$moveToTemp) {
        return response::json('error', 403);
      }

//      $imageItem = $this->_addImageToBo($imageFile);
//      echo '<pre>';
//      print_r($imageItem);
      die('here');
    }

    public function postGetMoreImages()
    {
      $response = [
        "success" => TRUE,
        "result"  => []
      ];

      $data = [
        'ids'     => Input::get('ids'),
        'amount'  => Input::get('amount'),
        'quality' => Input::get('quality')
      ];

      $rules = [
        'ids' => 'required'
      ];

      $validator = Validator::make(
        $data,
        $rules
      );

      if ($validator->fails()) {
        $response['success'] = FALSE;
        $response['result'] = $validator->messages();

        return Response::json($response, 200);
      }

      $ids = explode(",", $data['ids']);
      $amount = isset($data['amount']) ? $data['amount'] : 60;
      $quality = isset($data['quality']) ? intval($data['quality']) : FALSE;
      $images = $this->_getMoreImages($ids, $amount, $quality);

      $response = [
        "result" => $images
      ];

      return Response::json($response, 200);
    }

    private function _addImageTempFolder($imageFile)
    {
      // Prepare Image information
      $destinationPath = Config::get('path.internal.temp_media');
      $originalFilename = $imageFile->getClientOriginalName();
      $extension = pathinfo($originalFilename, PATHINFO_EXTENSION);
      $withoutExt = preg_replace('/\\.[^.\\s]{3,4}$/', '', $originalFilename);
      $mediaType = $this->_getMediaType($extension);

      // Check if you got type of file allowed
      if (!$mediaType) {
        RETURN FALSE;
      }

      // Try to move the file.
      $newFilename = urlize($withoutExt);
      $finalName = $newFilename . '.' . $extension;
      $finalName = $this->_preventCollidingFilenames($destinationPath, $finalName, $newFilename, $extension);
      try {
        $moveSuccess = $imageFile->move($destinationPath, $finalName);
      } catch (Exception $e) {
        return FALSE;
      }

      if ($moveSuccess) {
        // Generate hash for temp image.
        return TRUE;
      } else {
        return FALSE;
      }

      return TRUE;
    }

    private function _addImageToBo($imageFile, $relatedTypeBO = 'submission', $user = FALSE)
    {
      $relatedType = $relatedTypeBO;
      $destinationPath = Config::get('path.internal.media');
      $originalFilename = $imageFile->getClientOriginalName();
      $mimeType = $imageFile->getMimeType();
      $extension = $this->_getExtension($mimeType); //pathinfo($originalFilename, PATHINFO_EXTENSION);
      $withoutExt = preg_replace('/\\.[^.\\s]{3,4}$/', '', $originalFilename);

      // Check if Media Type is allowed.
      $mediaType = $this->_getMediaType($extension);

      if (!$mediaType) {
        Log::error("=== IMAGE ERROR 2 ===");
        Log::error($mediaType);
        Log::error("=== IMAGE ERROR 2 ===");

        RETURN FALSE;
//        return Response::json('error', 403);
      }

      if ($user !== FALSE) {
        $newFilename = 'imhere_' . $user->tracking->hash;
      } else {
        $newFilename = urlize($withoutExt);
      }

      $finalName = $newFilename . '.' . $extension;

      Log::error('=== FINAL NAME ===');
      Log::error($finalName);
      Log::error('=== FINAL NAME ! ===');

      //Checks for colliding filenames
      $finalName = $this->_preventCollidingFilenames($destinationPath, $finalName, $newFilename, $extension);

      $finalDestinationPath = $destinationPath . '/' . $finalName;

      Log::error('=== FINAL NAME 2 ===');
      Log::error($finalName);
      Log::error('=== FINAL NAME 2 ! ===');
      try {
        $moveSuccess = $imageFile->move($destinationPath, $finalName);
      } catch (Exception $e) {
        Log::error("=== IMAGE ERROR 3 ===");
        Log::error($e);
        Log::error("=== IMAGE ERROR 3 ===");

        return FALSE;
//        return Response::json('error', 403);
      }

      if ($moveSuccess) {
        $mediaItem = new MediaItem([
          'filename'          => $finalName,
          'original_filename' => $originalFilename,
          'title'             => $originalFilename,
          'extension'         => $extension,
          'related_type'      => $relatedType,
          'media_type'        => $mediaType,
          'backend_user_id'   => 1
        ]);

        if ($mediaType == MediaItem::MEDIA_TYPE_IMAGE) {
          //Generates internal thumbnail
          try {
            $img = Image::make($finalDestinationPath);
          } catch (Exception $e) {
            Log::error("=== IMAGE ERROR 4 ===");
            Log::error($finalDestinationPath);
            Log::error($e);
            Log::error(Input::all());
            Log::error("=== IMAGE ERROR 4 ===");

            return FALSE;
//            return Response::json('error', 400);
          }
          $mediaItem->width = $img->width();
          $mediaItem->height = $img->height();
          $img->fit(200, 200);
          $img->save(Config::get('path.internal.thumbs') . '/' . getFileNameSize($finalName, '200x200'));


          $img = Image::make($finalDestinationPath);
          $img
            ->resize(1200, 1200, function ($constraint) {
              $constraint->aspectRatio();
            })
            ->resizeCanvas(1200, 1200)
            ->save(Config::get('path.internal.thumbs') . '/' . getFileNameSize($finalName, 'Resize1200x1200'));

          $img = Image::make($finalDestinationPath);
          $img
            ->resize(1080, 1080, function ($constraint) {
              $constraint->aspectRatio();
            })
            ->resizeCanvas(1080, 1080)
            ->save(Config::get('path.internal.thumbs') . '/' . getFileNameSize($finalName, 'Resize1080x1080'));


          $img = Image::make($finalDestinationPath);
          $img
            ->resize(768, 768, function ($constraint) {
              $constraint->aspectRatio();
            })
            ->resizeCanvas(768, 768)
            ->save(Config::get('path.internal.thumbs') . '/' . getFileNameSize($finalName, 'Resize768x768'));


          $img = Image::make($finalDestinationPath);
          $img
            ->resize(384, 384, function ($constraint) {
              $constraint->aspectRatio();
            })
            ->resizeCanvas(384, 384)
            ->save(Config::get('path.internal.thumbs') . '/' . getFileNameSize($finalName, 'Resize384x384'));


          $img = Image::make($finalDestinationPath);
          $img
            ->resize(12, 12, function ($constraint) {
              $constraint->aspectRatio();
            })
            ->resizeCanvas(12, 12)
            ->save(Config::get('path.internal.thumbs') . '/' . getFileNameSize($finalName, 'Resize12x12'));
        }

        try {
          $mediaItem->save();
        } catch (Exception $e) {
          Log::error("=== IMAGE ERROR 5 ===");
          Log::error($e);
          Log::error("=== IMAGE ERROR 5 ===");

          return FALSE;
//          return Response::json('error', 400);
        }

        return $mediaItem;
      } else {
        Log::error("=== IMAGE ERROR 7 ===");
        Log::error($moveSuccess);
        Log::error("=== IMAGE ERROR 7 ===");

        return FALSE;
//        return Response::json('error', 400);
      }
    }

    private function _getMediaType($ext)
    {
      $allowedExts = Config::get('backoffice/media.allowedExts');

      foreach ($allowedExts as $type => $allowedExt) {
        if (in_array($ext, $allowedExt)) {
          return $type;
        }
      }

      return FALSE;
    }

    private function _generateSlug($originSlug, $langId)
    {
      $originSlug = urlize($originSlug);
      $slug = $originSlug;

      $slugCounter = 1;
      while (WebsiteObject::hasSlug($slug, $langId) && $slugCounter <= 80000) {
        $slug = $originSlug . "-" . $slugCounter;
        $slugCounter++;
      }

      if ($slugCounter == 80000) {
        return FALSE;
      } else {
        return $slug;
      }
    }

    private function _preventCollidingFilenames($destinationPath, $finalName, $newFilename, $extension)
    {
      $i = 1;
      while (file_exists($destinationPath . '/' . $finalName)) {
        $finalName = $newFilename . '-' . $i . '.' . $extension;
        $i++;
        //for safety
        if ($i > 40000) {
          return Response::json('error', 400);
        }
      }

      return $finalName;
    }

    private function _createUser($email)
    {

      DB::beginTransaction();
      try {
        $user = new User();
        $user->email = $email;
        $user->ip = Request::ip();
        $user->terms = 1;
        $user->submission_language_id = getActiveLanguage();
        $user->save();

        foreach (LaravelLocalization::getSupportedLocales() as $localeCode => $properties) {
          $userLang = new UserLanguage();
          $userLang->title = $user->id . '_' . $localeCode;
          $userLang->language_id = $localeCode;
          $userLang->user()->associate($user);
          $userLang->save();
        }

        $baseUri = Lang::get('routes.uri_users', [], 'de');
        $this->_generateWebsiteObjects($user, 'user', $baseUri);
        $this->_generateTracking($user);
        DB::commit();

        return $user;
      } catch (Exception $e) {
        DB::rollback();
        Log::error($e);
        throw($e);
      }
    }

    private function _checkUserExists($email)
    {
      $user = User::email($email)->first();

      return $user;
    }

    private function _createSubmission($user, $originalImage, $treatedImage)
    {

      DB::beginTransaction();

      try {
        $submission = new Submission();
        $submission->user_id = $user->id;
        $submission->originalImage()->associate($originalImage);
        $submission->finalImage()->associate($treatedImage);
        $submission->save();

        foreach (LaravelLocalization::getSupportedLocales() as $localeCode => $properties) {
          $submissionLang = new SubmissionLanguage();
          $submissionLang->title = $submission->id . '_' . $localeCode;
          $submissionLang->language_id = $localeCode;
          $submissionLang->submission()->associate($submission);
          $submissionLang->save();
        }

        $baseUri = Lang::get('routes.uri_submissions', [], 'de');
        $this->_generateWebsiteObjects($submission, 'submission', $baseUri);

        if ($submission->finalImage->width > 1200) {
          $submission->high_quality = 1;
          $submission->save();
        }

        DB::commit();

      } catch (Throwable $e) {
        DB::rollback();
        Log::error($e);
        throw($e);
      }

      return $submission;


    }

    private function _createDonation($user, $amount)
    {

      DB::beginTransaction();

      try {
        $donation = new Donation();
        $donation->user_id = $user->id;
        $donation->donation_amount = $amount;
        $donation->save();

        foreach (LaravelLocalization::getSupportedLocales() as $localeCode => $properties) {
          $donationLang = new DonationLanguage();
          $donationLang->title = $donation->id . '_' . $localeCode;
          $donationLang->language_id = $localeCode;
          $donationLang->donation()->associate($donation);
          $donationLang->save();
        }

        $baseUri = Lang::get('routes.uri_donations', [], 'de');
        $this->_generateWebsiteObjects($donation, 'donation', $baseUri);
        DB::commit();

        return $donation;
      } catch (Exception $e) {
        DB::rollback();
        Log::error($e);
        throw($e);
      }

    }

    private function _generateWebsiteObjects($object, $contentType, $baseUri)
    {

      DB::beginTransaction();

      try {
        $objectClass = get_class($object);
        $objectSlug = $this->_generateSlug($object->id . '_' . $objectClass, 'en');

        $websiteObject = new WebsiteObject();
        $websiteObject->object_id = $object->id;
        $websiteObject->object_type = $objectClass;
        $websiteObject->content_type = $contentType;
        $websiteObject->slug = $objectSlug;
        $websiteObject->uri = $baseUri . '/' . $objectSlug;
        $websiteObject->status = 'published';
        $websiteObject->save();

        foreach (LaravelLocalization::getSupportedLocales() as $localeCode => $properties) {
          $woLang = new WebsiteObjectLanguage();
          $woLang->website_object_id = $websiteObject->id;
          $woLang->wo_language_id = $localeCode;
          $woLang->lang_slug = $objectSlug;
          $woLang->lang_uri = $baseUri . '/' . $objectSlug;
          $woLang->save();
        }
        DB::commit();

        return;
      } catch (Exception $e) {
        DB::rollback();
        Log::error($e);
        throw($e);
      }
    }

    private function _generateTracking($user)
    {
      DB::beginTransaction();
      try {

        $tracking = new Tracking();
        $tracking->user_id = $user->id;
        $tracking->hash = sha1($user->id . $user->email);

        $shareUrl = lang_url('/', getActiveLanguage()) . '?utm_content=' . $tracking->hash;
        $shareFB = $shareUrl . '&' . Lang::get('tracking.facebook_thank_you');
        $bitlyFacebook = $this->_generateBitly($shareFB);
        $tracking->bitly_facebook = $bitlyFacebook;

        $shareTW = $shareUrl . '&' . Lang::get('tracking.twitter_thank_you');
        $bitlyTwitter = $this->_generateBitly($shareTW);
        $tracking->bitly_twitter = $bitlyTwitter;

        $sharePint = $shareUrl . '&' . Lang::get('tracking.pinterest_thank_you');
        $bitlyPinterest = $this->_generateBitly($sharePint);
        $tracking->bitly_pinterest = $bitlyPinterest;

        $tracking->save();

        DB::commit();

        return TRUE;

      } catch (Exception $e) {
        DB::rollback();
        Log::error($e);
        throw($e);
      }
    }

    private function _generateBitly($url)
    {
      $bitlyUrl = Bitly::shorten($url);

      return $bitlyUrl->data->url;
    }

    private function _getExtension($mimeType)
    {
      if ($mimeType == "image/jpeg") {
        return "jpg";
      } else if ($mimeType == "image/png") {
        return "png";
      }

      return "";
    }

    private function _getMoreImages($filterIds, $amount, $hq = FALSE)
    {
      $extraImages = GalleryService::getImages($filterIds, $amount, $hq);

      return $extraImages;
    }
  }
