<?php
/**
 * Created by PhpStorm.
 * User: software
 * Date: 10/31/17
 * Time: 10:44 AM
 */

namespace App\Tools;


use App\Person;
use App\TargetFilter;
use Carbon\Carbon;

class TMNTools
{
    // get nodes
    public function nodes()
    {
        $nodes = TargetFilter::jstree();
        return $nodes;
    }

    // regions
    public function regions()
    {
        $data = [
            'Ashanti',
            'Brong-Ahafo',
            'Central',
            'Eastern',
            'Greater Accra',
            'Northern',
            'Upper East',
            'Upper West',
            'Volta',
            'Western'
        ];

        return $data;
    }

    // convert selection to filter
    public function filterize($data)
    {
        $filter = ['country' => 'ghana'];
        $nodes  = [];
        if (array_key_exists('nodes', $data))
        {
            $nodes = is_array($data['nodes']) ? $data['nodes'] : json_decode($data['nodes'], true);
        }

        if (!is_array($nodes)) $data['nodes'] = [];
        // primary
        foreach ($data as $name => $val)
        {
            if ($name == 'nodes') continue;
            if (!in_array($name, ['tree', 'name', 'mode']))
            {
                // convert to lowercase: if value != array, proceed
                if (!is_array($val)) $filter[$name] = strtolower($val);
                else
                {
                    foreach ($val as $item) // process all elements
                    {
                        $filter[$name][] = strtolower($item);
                    }
                }
            }
        }

        // tree
        if (count($nodes) > 0)
        {
            $exe = TargetFilter::whereIn('id', $nodes)->chunk(50, function ($items) use (&$filter)
            {
                $items->each(function($item) use (&$filter)
                {
                    if ($item->folder != null)
                        $filter[$item->folder->alias][] = strtolower($item->name);
                });
            });
        }

        return $filter;
    }

    // get routes
    public function route($name = "aud.index")
    {
        $user = auth()->user();
        $role = strtolower($user->role->name);
        $link = $role != 'user' ? $role.'.ads.aud.index' : 'app.ads.aud.index';
        $repo = [
            // audiences
            'aud.index'     => $role != 'user' ? $role.'.ads.aud.index' : 'app.ads.aud.index',
            'aud.create'    => $role != 'user' ? $role.'.ads.aud.create' : 'app.ads.aud.create',
            'aud.view'      => $role != 'user' ? $role.'.ads.aud.view' : 'app.ads.aud.view',
            'aud.edit'      => $role != 'user' ? $role.'.ads.aud.edit' : 'app.ads.aud.edit',
            'aud.del'       => $role != 'user' ? $role.'.ads.aud.del' : 'app.ads.aud.del',

            // adverts
            'sms.send'      => $role != 'user' ? $role.'.ads.sms.send' : 'app.ads.sms.send',
            'email.send'    => $role != 'user' ? $role.'.ads.email.send' : 'app.ads.email.send'
        ];

        foreach ($repo as $key => $route)
            if ($key == $name)
                return $route;

        return $link;
    }

    // get available columns
    public function columns()
    {
        $data   = ['date_of_birth', 'gender', 'income', 'country', 'region', 'city', 'language'];
        $items  = TargetFilter::select('parent')->distinct()->get();
        $items->each(function($item) use (&$data) {
            if ($item->parent > 0)
            {
                $item = TargetFilter::find($item->parent);
                $data[] = $item->alias;
            }
        });
        sort($data);
        return $data;
    }

    // get people and stat by filter
    public function people($filters, $mode)
    {
        $info   = ['first_name', 'last_name', 'full_name', 'email', 'phone_number'];
        $prime  = ['country', 'region', 'city', 'age_from', 'age_to', 'gender', 'language'];
        $query  = Person::query();
        $age_f  = 0;
        $age_t  = 0;

        $people = $query->where(function($q) use(&$filters, $mode, $prime, &$age_f, &$age_t)
        {
            if (is_array($filters) && $filters != null)
            {
                foreach ($filters as $key => $data)
                {
                    $key = trim($key); // remove whitespace
                    if ($data == null) continue;
                    if (in_array($key, $prime)) // primary
                    {
                        if (is_array($data)) // multiple
                        {
                            if (count($data) == 0) continue;
                            $q->where(function($q) use ($key, $data) {
                                foreach ($data as $item)
                                {
                                    $item = strtolower(trim($item));
                                    if ($key == 'gender')
                                    {
                                        $q->orWhere('meta->'.$key, $item);
                                        continue;
                                    }
                                    else
                                    {
                                        $q->orWhere('meta->'.$key, 'like', '%'.$item.'%');
                                        continue;
                                    }
                                }
                            });
                            continue;
                        }
                        else // single
                        {
                            $now = Carbon::now()->startOfYear();
                            if (in_array($key, ['age_from', 'age_to'])) // birth dates
                            {
                                if ($key == 'age_from')
                                {
                                    $age    = $filters['age_from'] != null ? $filters['age_from'] : 13;
                                    $age    = (strpos($age, '+') !== false) ? 100 : $age;
                                    $age    = -1 * abs($age);
                                    $age_f  = $now->copy()->addYears($age)->year;
                                    continue;
                                }

                                if ($key == 'age_to')
                                {
                                    $age    = $filters['age_to'] != null ? $filters['age_to'] : 100;
                                    $age    = (strpos($age, '+') !== false) ? 100 : $age;
                                    $age    = -1 * abs($age);
                                    $age_t  = $now->copy()->addYears($age)->year;
                                    continue;
                                }
                                continue;
                            }

                            // other single items
                            $q->where(function($q) use (&$key, &$data) {
                                $q->orWhere('meta->'.$key, 'like', '%'.strtolower($data).'%');
                            });
                        }
                    }
                }
                // handle age or birth year
                $q->where(function($q) use (&$age_f, &$age_t) {
                    // normalize age_f & age_t
                    if ($age_t < $age_f) $age_f ^= $age_t ^= $age_f ^= $age_t;
                    $q->whereBetween('meta->birth_year', [$age_f, $age_t]);
                });
            }
            return $q;
        });

        // secondary OR optional (tree)
        $people = $people->where(function($q) use ($filters, $mode, $prime) {
            $q->where(function($q) use ($filters, $mode, $prime) {
                foreach ($filters as $key => $data)
                {
                    if ($data ==  null || in_array($key, $prime)) continue;
                    if (is_array($data)) // multiple
                    {
                        foreach ($data as $item)
                        {
                            $item = strtolower($item);
                            if ($mode == 'MATCH_EXACT')
                                $q->where('meta->'.$key, 'like', '%'.$item.'%');
                            else
                                $q->orWhere('meta->'.$key, 'like', '%'.$item.'%');
                        }
                        continue;
                    }
                    else // single
                    {
                        $data = strtolower($data);
                        if ($mode == 'MATCH_EXACT')
                            $q->where('meta->'.$key, 'like', '%'.$data.'%');
                        else
                            $q->orWhere('meta->'.$key, 'like', '%'.$data.'%');
                        continue;
                    }
                }
            });
            return $q;
        })->get($info);

        // statistics
        $total          = Person::all()->count();
        $data['people'] = $people;
        $data['reach']  = $people->count();
        $data['share']  = @($data['reach'] / $total) === false ? 0 : @($data['reach'] / $total) * 100;
        $data['total']  = $total;

        return (object) $data;
    }


    // get base layout
    public function base()
    {
        $user = auth()->user();
        $role = strtolower($user->role->name);
        $base = $role != 'user' ? $role . '.layouts.master' : 'app';
        return $base;
    }
}