<?php

use Facebook\Exceptions\FacebookResponseException;
use Facebook\Exceptions\FacebookSDKException;
use Facebook\Facebook;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Input;
use Mews\Purifier\Facades\Purifier;
use Support\Facades\JWTBandAuth;
use Support\Facebook\Guzzle6HttpClient;
use Tymon\JWTAuth\Exceptions\JWTException;

class APIController extends Controller
{
    /**
     * Registers and email in the teaser phase-
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function teaserRegister()
    {
        $status = Contest::status();

        // Bail if not in teaser phase
        if (!in_array($status, array('teaser'))) {
            return APIResponse::fail(401, [
                'contest_status' => trans('api.messages.not_in_teaser_phase')
            ]);
        }

        $email = Request::get('email');
        $name = Request::get('name');
        $name = strip_tags($name);

        $validator = Validator::make(
            array('email' => $email),
            array('email' => 'required|email')
        );

        if ($validator->fails()) {
            $messages = $validator->messages();
            return APIResponse::fail(400, [
                'email' => $messages->first('email'),
            ]);
        }

        $reminder = ContestReminder::firstOrNew(['email' => $email]);

        if (!$reminder->exists) {

            $reminder->email = $email;
            $reminder->name = $name;

            try {

                $reminder->save();
            } catch (Exception $ex) {

                return APIResponse::fail(500, [
                    'exception' => trans('api.messages.error_saving').':'.$ex->getMessage(),
                ]);
            }
        }

        return APIResponse::success([
            'reminder' => $reminder,
        ]);
    }

    /**
     * Gets the Contest details
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function contestDetails()
    {
        $contestDatesAndTimes = Contest::getContestOptionsWithPrefixes(['date', 'time']);

        unset($contestDatesAndTimes['date_teaser']);
        unset($contestDatesAndTimes['date_end_teaser']);

        return APIResponse::success([
            'details' => $contestDatesAndTimes,
        ]);
    }

    /**
     * Registers a voter and sends him an email with the token
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function voterRegister()
    {

        $data = Input::only('email');

        Validator::extend('more_disposable_emails', function ($attribute, $value, $parameters) {
            if (strpos($value, '@') === false) {
                return false;
            }

            list($local_part, $domain) = explode('@', $value);

            if (!$domain) {
                return false;
            }

            $invalidDomains = Config::get('invalid-email-domains');

            if (in_array($domain, $invalidDomains)) {
                return false;
            }

            return true;
        });

        $data['email'] = Purifier::clean($data['email']);

        $validator = Validator::make($data, [
            'email' => 'required|email|more_disposable_emails',
        ]);

        if ($validator->fails()) {
            $errors = $validator->messages()->toArray();

            return APIResponse::fail(401, $errors);
        }


        $band_id = Input::get('band_id');
        $band = Band::find($band_id);

        if (is_null($band)) {
            return APIResponse::fail(404, [
                'band' => trans('api.messages.band_not_found'),
            ]);
        }

        unset($data['lang']);

        $voter = Voter::firstOrCreate($data);
        $voter->token = sha1(str_random(20));
        $voter->save();

        try {
            $token = JWTAuth::fromUser($voter, [
                'model' => Voter::class,
            ]);
        } catch (JWTException $e) {
            return APIResponse::fail(500, [
                'token' => trans('api.messages.login_token_generation')
            ]);
        }

        $voter->sendToken($band_id, $token);

        return APIResponse::success([
            'success' => true,
        ]);
    }

    /**
     * Facebook voter login
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function voterFacebookLogin()
    {
        $data = Input::only('facebook_access_token');

        $validator = Validator::make($data, [
            'facebook_access_token' => 'required'
        ]);

        if ($validator->fails()) {
            return APIResponse::fail(400, $validator->messages()->toArray());
        }

        $facebookCredencials = Contest::facebookApp();

        $client = new Client();
        $fb = new Facebook([
            'app_id'                => $facebookCredencials['client_id'],
            'app_secret'            => $facebookCredencials['client_secret'],
            'default_graph_version' => 'v9.0',
            'http_client_handler'   => new Guzzle6HttpClient($client),
        ]);

        try {
            // Returns a `Facebook\FacebookResponse` object
            $response = $fb->get('/me?fields=id,name,email', $data['facebook_access_token']);
        } catch (FacebookResponseException $e) {
            Log::error($e);
            return APIResponse::fail(400, trans('api.messages.login_facebook_error'));
        } catch (FacebookSDKException $e) {
            Log::error($e);
            return APIResponse::fail(400, trans('api.messages.login_facebook_error'));
        }

        $fbUser = $response->getGraphUser();

        if (empty($fbUser['email'])) {
            return APIResponse::fail(400, trans('api.messages.login_facebook_email_missing'));
        }

        $credentials = [
            'facebook_id' => $fbUser['id'],
            'name'        => $fbUser['name'],
            'email'       => $fbUser['email']
        ];

        $voter = Voter::where('facebook_id', $credentials['facebook_id'])
            ->first();

        if (is_null($voter)) {
            $voter = Voter::where('email', $credentials['email'])
                ->first();

            if (is_null($voter)) {
                $voter = Voter::firstOrCreate($credentials);
            } else {
                if (!is_null($voter->facebook_id) && $voter->facebook_id !== $credentials['facebook_id']) {
                    return APIResponse::fail(500, [
                        'token' => trans('api.messages.login_invalid_facebook')
                    ]);
                } else {
                    $voter->facebook_id = $credentials['facebook_id'];
                    $voter->save();
                }
            }
        } else {
            if ($voter->email !== $fbUser['email']) {
                $voterEmail = Voter::where('email', $fbUser['email'])
                    ->first();
                if (!is_null($voterEmail)) {
                    return APIResponse::fail(500, [
                        'token' => trans('api.messages.login_invalid_facebook')
                    ]);
                }
            }
            $voter->email = $credentials['email'];
            $voter->save();
        }

        try {
            $token = JWTAuth::fromUser($voter, [
                'model' => Voter::class,
            ]);
        } catch (JWTException $e) {
            return APIResponse::fail(500, [
                'token' => trans('api.messages.login_token_generation')
            ]);
        }

        return APIResponse::success([
            'token' => $token
        ]);
    }

    /**
     * Login by email for the voter
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function voterLogin()
    {
        $credentials = Input::only('email');

        $validator = Validator::make($credentials, [
            'email' => 'required|email',
        ]);

        if ($validator->fails()) {
            return APIResponse::fail(400, [
                'credentials' => trans('api.messages.login_invalid_credentials')
            ]);
        }

        $voter = Voter::where('email', $credentials['email'])->first();

        if (is_null($voter)) {
            return APIResponse::fail(401, [
                'credentials' => trans('api.messages.login_invalid_credentials')
            ]);
        }

        try {

            $token = JWTAuth::fromUser($voter, [
                'model' => Voter::class,
            ]);
        } catch (JWTException $e) {
            return APIResponse::fail(500, [
                'token' => trans('api.messages.login_token_generation')
            ]);
        }

        return APIResponse::success([
            'token' => $token
        ]);
    }


    /**
     * Gets the votes by a logged in voter.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function getVotesByVoter()
    {
        $voter = JWTAuth::toUser();

        if (is_null($voter)) {
            return APIResponse::fail(404, [
                'voter' => trans('api.messages.voter_not_found'),
            ]);
        }

        $votes = Vote::select('band_id')->where('voter_id', $voter->id)->get();

        $response = array_map(function ($vote) {
            return $vote['band_id'];
        }, $votes->toArray());

        return APIResponse::success([
            'votedIn' => $response,
        ]);
    }

    /**
     * Makes a vote to a band with a specific slug
     *
     * @param  string  $bandSlug  Slug of the band
     * @return \Illuminate\Http\JsonResponse
     */
    public function vote($bandSlug)
    {
        $voter = JWTAuth::toUser();

        $status = Contest::status();

        if (!in_array($status, array('participate', 'vote', 'semi-final'))) {
            return APIResponse::fail(500, [
                'phase' => trans('api.messages.invalid_phase'),
            ]);
        }

        $band = Band::where('slug', $bandSlug)->first();

        if (is_null($band)) {
            return APIResponse::fail(404, [
                'band' => trans('api.messages.band_not_found'),
            ]);
        }

        if ($band->rejected || !$band->approved) {
            return APIResponse::fail(403, [
                'band' => trans('api.messages.band_not_eligible'),
            ]);
        }


        $data = Input::only('ip');

        $validator = Validator::make($data, [
            'ip' => 'required|ip',
        ]);

        if ($validator->fails()) {
            $messages = $validator->messages()->toArray();
            return APIResponse::fail(403, $messages);
        }

        $phase = ($status === 'semi-final') ? 'semi-final' : 'initial';
        $bandId = $band->id;
        $voterId = $voter->id;
        $ip = $data['ip'];


        /*
        Seems like redundant code, there is a firstOrNew below and an exists validation
        Unnecessary query?
        $vote = Vote::where('voter_id', $voterId)
            ->where('band_id', $bandId)
            ->first();

        if(!is_null($vote)) {
            return APIResponse::fail(403, [
                'vote' => trans('api.messages.repeated_vote'),
            ]);
        } */


        $data = [
            'phase'    => $phase,
            'voter_id' => $voterId,
            'band_id'  => $bandId
        ];

        $vote = Vote::firstOrNew($data);

        if ($vote->exists) {
            return APIResponse::fail(403, [
                'vote' => trans('api.messages.repeated_vote'),
            ]);
        }

        $vote->ip = $ip;
        $vote->save();

        return APIResponse::success([
            'success' => true,
        ]);
    }

    /**
     * Gets email and password and sends a token to be used on login-secured routes.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function bandLogin()
    {
        $credentials = Input::only('email', 'password');
        $validator = Validator::make($credentials, [
            'email'    => 'required|email',
            'password' => 'required',
        ]);

        if ($validator->fails()) {
            return APIResponse::fail(401, [
                'credentials' => trans('api.messages.login_invalid_credentials')
            ]);
        }

        $band = Band::where('email', $credentials['email'])->first();

        if (is_null($band)) {
            return APIResponse::fail(401, [
                'credentials' => trans('api.messages.login_invalid_credentials')
            ]);
        }

        $passwordCheck = Hash::check($credentials['password'], $band->password);

        if (!$passwordCheck) {
            return APIResponse::fail(401, [
                'credentials' => trans('api.messages.login_invalid_credentials')
            ]);
        }

        try {

            $token = JWTBandAuth::fromUser($band, ['model' => Band::class]);
        } catch (JWTException $e) {
            return APIResponse::fail(500, [
                'token' => trans('api.messages.login_token_generation')
            ]);
        }

        return APIResponse::success([
            'token' => $token
        ]);
    }

    /**
     * Registers a band.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function registerBand()
    {
        $status = Contest::status();

        if (!in_array($status, ['participate', 'vote'])) {
            return APIResponse::fail(401, [
                'contest_status' => trans('api.messages.not_in_participate_phase'),
            ]);
        }

        if ($status === 'vote' && Contest::getDate('semi-final-limbo')->isSameAs('Y-m-d')) {
            return APIResponse::fail(401, [
                'contest_status' => trans('api.messages.not_in_participate_phase'),
            ]);
        }

        $data = Request::all();

        if (count($data) > 0) {
            foreach ($data as $idx => $item) {
                if ($idx == 'image') {
                    continue;
                }

                if (!is_array($item)) {
                    $data[$idx] = Purifier::clean($item);
                } else {
                    foreach ($item as $idxItem => $subitem) {
                        $data[$idx][$idxItem] = Purifier::clean($subitem);
                    }
                }
            }
        }

        if (!array_key_exists('names', $data) || !array_key_exists('functions', $data)) {
            $errors = [];

            if (!array_key_exists('names', $data)) {
                $errors['names'] = trans('api.messages.param_missing');
            }

            if (!array_key_exists('names', $data)) {
                $errors['functions'] = trans('api.messages.param_missing');
            }

            return APIResponse::fail(400, $errors);
        }

        $members = [];

        foreach ($data['names'] as $index => $name) {
            if ($name === '' || $data['functions'][$index] === '') {
                break;
            }

            array_push($members, [
                'name'     => $name,
                'function' => $data['functions'][$index]
            ]);
        }

        if (!count($members)) {
            return APIResponse::fail(500, [
                'members' => trans('api.messages.not_enough_members')
            ]);
        }

        Validator::extend('youtube_url', 'Support\YoutubeUrlValidator@validateYoutubeUrl');

        $rules = Band::rules();

        if (Contest::getEdition() === 'pt-BR') {
            $rules['state'] = 'required|max:255';
        }

        $rules['nationality'] = 'required|max:255';
        $rules['email'] .= '|unique:bands';
        $rules['alternative_email'] .= '|unique:bands';
        $rules['video_url'] .= '|youtube_url';

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

        if ($validator->fails() || !Input::hasFile('image')) {

            $errors = $validator->messages()->toArray();

            if (!Input::hasFile('image')) {
                $errors['image'] = trans('api.messages.param_missing');
            }

            return APIResponse::fail(400, $errors);
        }

        unset($data['functions']);
        unset($data['names']);
        unset($data['lang']);

        $submittedImageObj = Input::file('image');
        $submittedImagePath = $submittedImageObj->getPathName();
        $imageData = file_get_contents($submittedImagePath);

        try {
            imagecreatefromstring($imageData);
        } catch (Exception $e) {
            return APIResponse::fail(500, [
                'image' => trans('errors.image_format'),
            ]);
        }

        $data['slug'] = Str::slug($data['name']);

        $extension = Input::file('image')->getClientOriginalExtension();
        $name = str_random(5).date('YmdHis').str_random(5);
        $path = public_path().'/uploads/band-images';
        $name = $name.".$extension";
        $image = Input::file('image')->move($path, $name);

        $data['password'] = Hash::make($data['password']);

        unset($data['agree']);
        unset($data['data_policy_accept']);
        unset($data['image']);

        try {
            $band = Band::create($data);

            try {

                if (file_exists($image->getPathName())) {
                    $band->addToMediaSlot('image', $image->getPathName());
                    $band->generateImageTypes();
                }
            } catch (Exception $e) {
                return APIResponse::fail(503, [
                    'image' => trans('api.messages.image_save_error')
                ]);
            }

            foreach ($members as $member) {
                BandMember::create(array_merge($member, ['band_id' => $band->id]));
            }
        } catch (\Exception $e) {
            return APIResponse::fail(400, [
                'band' => trans('api.messages.create_band_error').':'.$e->getMessage()
            ]);
        }

        $band = Band::find($band->id);

        return APIResponse::success([
            'band' => $band->getApiFormattedRecord(),
        ]);
    }


    /**
     * Gets a list of bands considering the stage the contest is in, expects the parameters below:
     * @param  integer  $offset  The search offset, defaults to 0
     * @param  integer  $limit  The number of records to get
     * @param  string  $searchCriteria  The criteria used if a search is being performed (Optional)
     */
    public function contextListBands()
    {
        $request = Input::all();
        $offset = isset($request['offset']) ? intval($request['offset']) : 0;
        $limit = isset($request['limit']) ? intval($request['limit']) : 10;
        $searchCriteria = isset($request['searchCriteria']) ? $request['searchCriteria'] : null;

        $bandsQ = Band::with('votes', 'semiFinalVotes')->ofType('approved');
        if (!empty($searchCriteria)) {
            $bandsQ->where('name', 'like', '%'.$searchCriteria.'%');
        }


        if (Contest::hasEnded()) {
            // If there are finalists, filter only finalists, except when winner has been chosen
            if (Contest::getDate('show-finalists')->isPast() && Band::ofType('approved')->orWhere('final',
                    true)->first()) {
                if (!Band::with('votes')->ofType('approved')->where('winner', true)->first()) {
                    $bandsQ->where('final', true);
                }
            } else {
                $bandsQ->where('shortlist', true);
            }
        } elseif (Contest::getDate('show-semi-finalists')->isPast()) {
            // If shortlist has been created, filter only shortlist entries
            if (Band::ofType('approved')->where('shortlist', true)->first()) {
                $bandsQ->where('shortlist', true);
            }
        }
        $totalRecords = $bandsQ->count();
        $bandsQ->skip($offset);
        $bandsQ->take($limit);
        $bandsQ->orderBy('name', 'asc');
        $bands = $bandsQ->get();
        $ret = [
            'total'  => $totalRecords,
            'limit'  => $limit,
            'offset' => $offset,
            'bands'  => []
        ];
        foreach ($bands as $band) {
            $ret['bands'][] = $band->getApiFormattedRecord();
        }
        return APIResponse::success($ret, trans('api.messages.success'));
    }


    /**
     * Gets a list of bands, expects the parameters below:
     * @param  integer  $offset  The search offset, defaults to 0
     * @param  integer  $limit  The number of records to get
     * @param  string  $searchCriteria  The criteria used if a search is being performed (Optional)
     */
    public function ListBands()
    {
        $request = Input::all();
        $offset = isset($request['offset']) ? intval($request['offset']) : 0;
        $limit = isset($request['limit']) ? intval($request['limit']) : 10;
        $searchCriteria = isset($request['searchCriteria']) ? $request['searchCriteria'] : null;

        $bandsQ = Band::with('votes', 'semiFinalVotes')->ofType('approved');
        if (!empty($searchCriteria)) {
            $bandsQ->where('name', 'like', '%'.$searchCriteria.'%');
        }
        $totalRecords = $bandsQ->count();
        $bandsQ->skip($offset);
        $bandsQ->take($limit);
        $bandsQ->orderBy('name', 'asc');
        $bands = $bandsQ->get();
        $ret = [
            'total'  => $totalRecords,
            'limit'  => $limit,
            'offset' => $offset,
            'bands'  => []
        ];
        foreach ($bands as $band) {
            $ret['bands'][] = $band->getApiFormattedRecord();
        }

        return APIResponse::success([
            'bands' => $ret,
        ]);
    }

    /**
     * Returns the top 10 bands
     */
    public function topBands()
    {
        $bandsRes = [];
        $bandsQ = Band::with(['media'])
            ->ofType('approved')
            ->join('votes', 'votes.band_id', '=', 'bands.id')
            ->select('bands.*', DB::raw('count(`votes`.`band_id`) as `votes_count`'))
            ->groupBy('votes.band_id')
            ->orderBy('votes_count', 'desc')
            ->orderBy('bands.created_at', 'asc')
            ->take(1);

        $bands = $bandsQ->get();
        foreach ($bands as $idx => $band) {
            $bandsRes[] = $band->getApiFormattedRecord();
        }

        return APIResponse::success([
            'bands' => $bandsRes,
        ]);
    }

    /**
     * Shows a band detail by id
     *
     * @param  int  $id
     * @return \Illuminate\Http\JsonResponse
     */
    public function showBand($id)
    {
        $band = Band::where('id', $id)->ofType('approved')->first();

        if (is_null($band)) {
            return APIResponse::fail(404, [
                'band' => trans('api.messages.band_not_found'),
            ]);
        }

        $res = $band->getApiDetailFormattedRecord();

        return APIResponse::success([
            'band' => $res,
        ]);
    }

    public function editBand($id)
    {
        /**
         * Extra security layer to do auth validation
         */
        try {
            $jwtAuth = JWTBandAuth::parseToken();
            $claims = $jwtAuth->getPayload();
            $model = $claims->get('model');

            if ($model !== Band::class) {
                return APIResponse::fail(404, [
                    'band' => trans('api.messages.band_not_found')
                ]);
            }

            $band = JWTBandAuth::toUser();

            if ($band->id != $id) {
                return APIResponse::fail(400, [
                    'error' => trans('api.messages.not_allowed')
                ]);
            }
        } catch (Exception $e) {
            return APIResponse::fail(500, [
                'login' => trans('api.messages.login_token_generation')
            ]);
        }

        if (is_null($band)) {
            return APIResponse::fail(500, [
                'band' => trans('api.messages.band_not_found'),
            ]);
        }

        // /**
        //  * Do band edit.
        //  */
        // if (Contest::status() !== 'participate') {
        //     return APIResponse::fail(500, [
        //         'contest_status' => trans('api.messages.not_in_participate_phase'),
        //     ]);
        // }

        $data = Request::all();

        if (count($data) > 0) {
            foreach ($data as $idx => $item) {
                if ($idx == 'image') {
                    continue;
                }

                if (!is_array($item)) {
                    $data[$idx] = Purifier::clean($item);
                } else {
                    foreach ($item as $idxItem => $subitem) {
                        $data[$idx][$idxItem] = Purifier::clean($subitem);
                    }
                }
            }
        }

        if (!array_key_exists('names', $data) || !array_key_exists('functions', $data)) {
            $errors = [];

            if (!array_key_exists('names', $data)) {
                $errors['names'] = trans('api.messages.param_missing');
            }

            if (!array_key_exists('names', $data)) {
                $errors['functions'] = trans('api.messages.param_missing');
            }

            return APIResponse::fail(400, $errors);
        }

        $members = [];

        foreach ($data['names'] as $index => $name) {
            if ($name === '' || $data['functions'][$index] === '') {
                break;
            }

            array_push($members, [
                'name'     => $name,
                'function' => $data['functions'][$index]
            ]);
        }

        if (!count($members)) {
            return APIResponse::fail(500, [
                'members' => trans('api.messages.not_enough_members')
            ]);
        }

        Validator::extend('youtube_url', 'Support\YoutubeUrlValidator@validateYoutubeUrl');

        $rules = Band::rules();
        $rules['image'] = 'image|max:2048';
        $rules['name'] = '';
        $rules['agree'] = '';
        $rules['data_policy_accept'] = '';
        $rules['accept_image_usage'] = '';
        $rules['accept_video_recording'] = '';
        $rules['email'] = '';
        $rules['alternative_email'] = '';
        $rules['password'] = '';
        $rules['video_url'] .= '|youtube_url';
        $rules['second_video_url'] = 'max:255|youtube_url';

        $bandSlug = $band->slug;
        $validator = Validator::make($data, $rules);

        if ($validator->fails()) {

            $errors = $validator->messages()->toArray();

            return APIResponse::fail(400, $errors);
        }

        if (Input::hasFile('image')) {
            $submittedImageObj = Input::file('image');
            $submittedImagePath = $submittedImageObj->getPathName();
            $imageData = file_get_contents($submittedImagePath);

            try {
                imagecreatefromstring($imageData);
            } catch (Exception $e) {
                return APIResponse::fail(500, [
                    'image' => trans('errors.image_format'),
                ]);
            }

            $extension = Input::file('image')->getClientOriginalExtension();
            $name = $bandSlug;
            $path = public_path().'/uploads/band-images';
            $name = $name.".$extension";
            $image = Input::file('image')->move($path, $name);
        }

        try {

            if (isset($image) && file_exists($image->getPathName())) {
                $band->addToMediaSlot('image', $image->getPathName());
                $band->generateImageTypes();
            }
        } catch (Exception $e) {
            return APIResponse::fail(503, [
                'image' => trans('api.messages.image_save_error')
            ]);
        }

        $band->alternative_name = $data['alternative_name'];
        $band->bio = $data['bio'];
        $band->song = $data['song'];
        $band->video_url = $data['video_url'];
        $band->phone = $data['phone'];
        $band->city = $data['city'];
        $band->alternative_phone = $data['alternative_phone'];
        $band->second_video_url = $data['second_video_url'];

        if (Contest::getEdition() === 'pt-BR') {
            $band->state = $data['state'];
        }

        $band->save();

        BandMember::where('band_id', $band->id)->delete();

        foreach ($members as $member) {
            BandMember::create(array_merge($member, ['band_id' => $band->id]));
        }

        return APIResponse::success([
            'band' => $band->getApiFormattedRecord(),
        ]);
    }

    /**
     * Generates promotional material for a band ID
     *
     * @param  int  $bandId
     * @return \Illuminate\Http\JsonResponse
     */
    public function generatePromotionalMaterial($bandId)
    {

        $edition = Contest::getEdition();

        $band = Band::find($bandId);

        if (is_null($band)) {
            return APIResponse::fail(404, [
                'band' => trans('api.messages.band_not_found'),
            ]);
        }

        $bandId = $band->id;
        $bandName = $band->name;
        $template = ucfirst(Input::get('template'));

        if (empty($template)) {
            return APIResponse::fail(400, [
                'template' => trans('api.messages.param_missing'),
            ]);
        }

        if (!in_array($template, ['Template_1', 'Template_2'])) {
            return APIResponse::fail(400, [
                'template' => trans('api.messages.invalid_template'),
            ]);
        }

        $zipFolderId = date('Y').'_'.$edition.'_'.$bandId.'_material_divulgacao_'.$template;
        $zipFilePAth = public_path().'/uploads/blitzes/'.$zipFolderId.".zip";

        switch ($template) {
            case 'Template_1':

                $bandName = mb_strtoupper($bandName, 'UTF-8');
                //$font = public_path() . "/assets/fonts/Bluescreens-Round-Bold.ttf";
                $font = public_path()."/assets/fonts/edp_preon_medium-webfont.ttf";

                // A4 PRINT

                $image1 = imagecreatefrompng(public_path()."/assets/img/blitz/{$edition}/cartaz_1/CartazA4-BG.png");
                $image_width = imagesx($image1);

                imagealphablending($image1, true);

                $white = imagecolorallocate($image1, 0, 0, 0);

                $fSizeInitial = 60;

                //makeTextBlock($text, $fontfile, $fontsize, $width)
                $finalText = $this->makeTextBlock($bandName, $font, $fSizeInitial, ($image_width * 2) / 2);
                //imagettfbbox ( float $size , float $angle , string $fontfile , string $text )
                for ($i = 0; $i < count($finalText); $i++) {
                    $bbox = imagettfbbox($fSizeInitial, 0, $font, $finalText[$i]);
                    $x = ceil(($image_width - $bbox[2]) / 2);

                    //the first y determines the position of the text in the image
                    //the next determines line spacing

                    if ($i == 0) {
                        //                        $dist = 600;
                        $dist = 2750;
                        $y = $dist;
                    } else {
                        $y = $y + 90;
                    }


                    // imagefttext("Image", "Font Size", "Rotate Text", "Left Position",
                    // "Top Position", "Font Color", "Font Name", "Text To Print");

                    imagefttext($image1, $fSizeInitial, 0, $x, $y, $white, $font, $finalText[$i]);
                }

                //COVER IMAGE

                $image2 = imagecreatefrompng(public_path()."/assets/img/blitz/{$edition}/cartaz_1/FB_Cover.png");
                $image_width = imagesx($image2);

                imagealphablending($image2, true);

                $white = imagecolorallocate($image2, 0, 0, 0);

                // makeTextBlock($text, $fontfile, $fontsize, $width)
                $finalText = $this->makeTextBlock($bandName, $font, 25, 330);

                for ($i = 0; $i < count($finalText); $i++) {

                    // imagettfbbox ( float $size , float $angle , string $fontfile , string $text )
                    $bbox = imagettfbbox(25, 0, $font, $finalText[$i]);

                    // the first y determines the position of the text in the image
                    // the next determines line spacing

                    if ($i == 0) {
                        $dist = 160;
                        $y = $dist;
                    } else {
                        $y = $y + 45;
                    }


                    // imagefttext("Image", "Font Size", "Rotate Text", "Left Position",
                    // "Top Position", "Font Color", "Font Name", "Text To Print");

                    imagefttext($image2, 25, 0, 100, $y, $white, $font, $finalText[$i]);
                }

                // POST IMAGE

                $image3 = imagecreatefrompng(public_path()."/assets/img/blitz/{$edition}/cartaz_1/FB_Post.png");
                $image_width = imagesx($image3);

                imagealphablending($image3, true);

                $white = imagecolorallocate($image3, 0, 0, 0);

                $finalText = $this->makeTextBlock($bandName, $font, 50, ($image_width * 2) / 3);

                for ($i = 0; $i < count($finalText); $i++) {
                    $bbox = imagettfbbox(50, 0, $font, $finalText[$i]);
                    $x = ceil(($image_width - $bbox[2]) / 2);

                    if ($i == 0) {
                        $dist = 1650;
                        $y = $dist;
                    } else {
                        $y = $y + 75;
                    }

                    imagefttext($image3, 50, 0, $x, $y, $white, $font, $finalText[$i]);
                }

                break;

            case 'Template_2':

                $fSizeInitial = 60;

                $bandName = mb_strtoupper($bandName, 'UTF-8');
                $font = public_path()."/assets/fonts/edp_preon_medium-webfont.ttf";

                //A4 PRINT

                $image1 = imagecreatefrompng(public_path()."/assets/img/blitz/{$edition}/cartaz_2/02CartazA4.png");
                $image_width = imagesx($image1);

                imagealphablending($image1, true);

                $white = imagecolorallocate($image1, 255, 255, 255);

                //makeTextBlock($text, $fontfile, $fontsize, $width)
                $finalText = $this->makeTextBlock($bandName, $font, $fSizeInitial, ($image_width * 2) / 2);
                //imagettfbbox ( float $size , float $angle , string $fontfile , string $text )
                for ($i = 0; $i < count($finalText); $i++) {
                    $bbox = imagettfbbox($fSizeInitial, 0, $font, $finalText[$i]);
                    $x = ceil(($image_width - $bbox[2]) / 2);

                    //the first y determines the position of the text in the image
                    //the next determines line spacing

                    if ($i == 0) {
                        $dist = 2750;
                        $y = $dist;
                    } else {
                        $y = $y + 90;
                    }


                    // imagefttext("Image", "Font Size", "Rotate Text", "Left Position",
                    //"Top Position", "Font Color", "Font Name", "Text To Print");

                    imagefttext($image1, $fSizeInitial, 0, $x, $y, $white, $font, $finalText[$i]);
                }

                //COVER IMAGE

                $image2 = imagecreatefrompng(public_path()."/assets/img/blitz/{$edition}/cartaz_2/Cartaz02CoverImage.png");
                $image_width = imagesx($image2);

                imagealphablending($image2, true);

                $white = imagecolorallocate($image2, 255, 255, 255);

                //makeTextBlock($text, $fontfile, $fontsize, $width)
                $finalText = $this->makeTextBlock($bandName, $font, 25, 345);
                //imagettfbbox ( float $size , float $angle , string $fontfile , string $text )
                for ($i = 0; $i < count($finalText); $i++) {
                    $bbox = imagettfbbox(25, 0, $font, $finalText[$i]);
                    $x = ceil(($image_width - $bbox[2]) / 2);

                    //the first y determines the position of the text in the image
                    //the next determines line spacing

                    if ($i == 0) {
                        $dist = 160;
                        $y = $dist;
                    } else {
                        $y = $y + 45;
                    }


                    // imagefttext("Image", "Font Size", "Rotate Text", "Left Position",
                    //"Top Position", "Font Color", "Font Name", "Text To Print");

                    imagefttext($image2, 25, 0, 100, $y, $white, $font, $finalText[$i]);
                }

                //POST IMAGE

                $image3 = imagecreatefrompng(public_path()."/assets/img/blitz/{$edition}/cartaz_2/Cartaz02PostImage.png");
                $image_width = imagesx($image3);

                imagealphablending($image3, true);

                $white = imagecolorallocate($image3, 255, 255, 255);

                //makeTextBlock($text, $fontfile, $fontsize, $width)
                $finalText = $this->makeTextBlock($bandName, $font, 50, ($image_width * 2) / 3);
                //imagettfbbox ( float $size , float $angle , string $fontfile , string $text )
                for ($i = 0; $i < count($finalText); $i++) {
                    $bbox = imagettfbbox(50, 0, $font, $finalText[$i]);
                    $x = ceil(($image_width - $bbox[2]) / 2);

                    //the first y determines the position of the text in the image
                    //the next determines line spacing

                    if ($i == 0) {
                        $dist = 1650;
                        $y = $dist;
                    } else {
                        $y = $y + 75;
                    }


                    // imagefttext("Image", "Font Size", "Rotate Text", "Left Position",
                    //"Top Position", "Font Color", "Font Name", "Text To Print");

                    imagefttext($image3, 50, 0, $x, $y, $white, $font, $finalText[$i]);
                }

                break;
        }

        ImagePng($image1, public_path().'/uploads/blitzes/'.$edition.'_'.$bandId.'_'.$template.'_1.png');
        ImagePng($image2, public_path().'/uploads/blitzes/'.$edition.'_'.$bandId.'_'.$template.'_cover_facebook.png');
        ImagePng($image3, public_path().'/uploads/blitzes/'.$edition.'_'.$bandId.'_'.$template.'_post_facebook.png');

        $imagesToInsert = [
            public_path().'/uploads/blitzes/'.$edition.'_'.$bandId.'_'.$template.'_1.png',
            public_path().'/uploads/blitzes/'.$edition.'_'.$bandId.'_'.$template.'_cover_facebook.png',
            public_path().'/uploads/blitzes/'.$edition.'_'.$bandId.'_'.$template.'_post_facebook.png'
        ];

        $imageNamesToInsert = [
            $edition.'_'.$bandId.'_'.$template.'_1.png',
            $edition.'_'.$bandId.'_'.$template.'_cover_facebook.png',
            $edition.'_'.$bandId.'_'.$template.'_post_facebook.png'
        ];


        //Convert Image 1 to PDF before Zipping

        $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
        // set auto page breaks
        $pdf->SetAutoPageBreak(false);

        $pdf->SetMargins(0, 0, 0);
        $pdf->SetHeaderMargin(0);
        $pdf->SetFooterMargin(0);

        // add a page


        $pdfName = $edition.'_'.$bandId.'_'.$template.'_cartaz.pdf';
        $pdfPath = public_path().'/uploads/blitzes/'.$pdfName;

        $pdf->AddPage('P', 'A4');


        //$pdf->Image(public_path().'/uploads/blitzes/'.$bandId.'_'.$template.'_1.png', '', '', 600, 850, 'PNG','', '', true, 200, '', false, false, 0, false, false, false);
        $pdf->Image($imagesToInsert[0], '', '', 0, 0, 'PNG', '', '', true, 200, '', false, false, 0, false, false,
            true);
        //Close and output PDF document
        $pdf->Output($pdfPath, 'F');
        //Once generation is over we need to Zip contents of the folder created
        //create an instance of ZipArchive class

        $zip = new ZipArchive();

        //create the archive called images.zip and open it

        if (file_exists($zipFilePAth)) {
            @unlink($zipFilePAth);
        }


        $result = $zip->open($zipFilePAth, ZIPARCHIVE::CREATE);

        if ($result) {

            foreach ($imagesToInsert as $idx => $imageToInsert) {
                $zip->addFile($imageToInsert, '/'.$imageNamesToInsert[$idx]);
            }
            $zip->addFile($pdfPath, '/'.$pdfName);


            $zip->close();

            $fields['zip-path'] = $zipFilePAth;
        }

        //remove generated Images from memory
        imagedestroy($image1);
        imagedestroy($image2);
        imagedestroy($image3);

        //Since the images are already zipped, remove them from the file system too.
        foreach ($imagesToInsert as $imageToInsert) {
            @unlink($imageToInsert);
        }
        @unlink($pdfName);


        return APIResponse::success([
            'fileUrl'  => URL::to('/').'/uploads/blitzes/'.basename($zipFolderId.'.zip'),
            'filename' => basename($zipFolderId.'.zip'),
            'filesize' => filesize($fields['zip-path']),
        ]);
    }

    private function makeTextBlock($text, $fontfile, $fontsize, $width)
    {
        $words = explode(' ', $text);
        $lines = array($words[0]);
        $currentLine = 0;
        for ($i = 1; $i < count($words); $i++) {
            $lineSize = imagettfbbox($fontsize, 0, $fontfile, $lines[$currentLine].' '.$words[$i]);
            if ($lineSize[2] - $lineSize[0] < $width) {
                $lines[$currentLine] .= ' '.$words[$i];
            } else {
                $currentLine++;
                $lines[$currentLine] = $words[$i];
            }
        }
        return $lines;
    }
}
