<?php

use \GuzzleHttp\Client;

$app = $this->app;

return [
    'name' => 'lokalize',
    'label' => 'Lokalize',
    'icon' => 'lokalize:icon.svg',
    'fields' => (function() use($app) {

        $projects = $app->module('lokalize')->projects([
            'fields' => ['values' => 0]
        ]);
        $options = [];

        foreach ($projects as $project) {

            $options[] = [
                'value' => $project['name'],
                'label' => $project['label'] ? $project['label'] : $project['name'],
            ];
        }

        return [
            [
                'name' => 'projects',
                'type' => 'select',
                'opts' => [
                    'options' => $options,
                    'multiple' => true
                ],
            ],

            [
                'name' => 'mode',
                'label' => 'Sync mode',
                'type' => 'select',
                'opts' => [
                    'default' => 'override',
                    'options' => [
                        ['value' => 'override', 'label' => 'Override'],
                        ['value' => 'missingKeys', 'label' => 'Missing keys only'],
                    ]
                ],
            ],
        ];
    })(),


    'sync:push' => function(array $settings = [], ?array $target = null, ?Client $client = null) {

        $run = 0;
        $limit = 20;

        $filter = null;
        $settings = array_merge([
            'syncAll' => true,
            'projects' => [],
            'mode' => 'override',
        ], $settings);

        if (!$settings['syncAll'] && count($settings['projects'])) {
            $filter = ['name' => ['$in' => $settings['projects']]];
        }

        while (true) {

            $projects = $this->dataStorage->find('lokalize/projects', [
                'filter' => $filter,
                'skip' => $run * $limit,
                'limit' => $limit
            ])->toArray();

            $payload = [
                'run' => $run,
                'projects' => $projects,
                'mode' => $settings['mode']
            ];

            if (count($projects)) {

                $client->request('POST', 'api/sync/job', [
                    'json' => [
                        'job' => 'lokalize',
                        'mode' => 'push',
                        'payload' => $this->helper('jwt')->encode($payload, $target['syncKey'])
                    ]
                ]);
            }

            if (!count($projects)) {
                break;
            }

            $run += 1;
        };

    },

    'on:push' => function($payload = null) {

        if (!isset($payload['projects'])) {
            return ['message' => 'no projects'];
        }

        $mode = $payload['mode'] ?? 'override';

        foreach ($payload['projects'] as $project) {

            $currentMode = $mode;
            $currentProject = $this->dataStorage->findOne('lokalize/projects', ['_id' => $project['_id']]);

            if (!$currentProject) {
                $currentMode = 'override';
            }

            // prevent mongodb error: no `.` allowed in field names on insert
            $keys = $project['keys'];
            $values = $project['values'];

            unset($project['keys'], $project['values']);

            switch ($currentMode) {
                case 'missingKeys':

                    // add missing keys
                    $keysCurrent = [];
                    $localsCurrent = [];

                    // sync keys
                    foreach ($currentProject['keys'] as $key) {
                        $keysCurrent[] = $key['name'];
                    }

                    foreach ($keys as $key) {
                        if (!in_array($key['name'], $keysCurrent)) $currentProject['keys'][] = $key;
                    }

                    $keys = $currentProject['keys'];

                    // sync locales
                    foreach ($currentProject['locales'] as $locale) {
                        $localsCurrent[] = $locale['i18n'];
                    }

                    foreach ($project['locales'] as $locale) {
                        if (!in_array($locale['i18n'], $localsCurrent)) $currentProject['locales'][] = $locale;
                    }

                    $project['locales'] = $currentProject['locales'];

                    // add missing values
                    foreach ($project['locales'] as $locale) {

                        $locale = $locale['i18n'];

                        if (!isset($currentProject['values'][$locale])) {
                            $currentProject['values'][$locale] = [];
                        }

                        foreach ($keys as $key) {

                            if (!isset($currentProject['values'][$locale][$key['name']])) {
                                $currentProject['values'][$locale][$key['name']] = ['value' => null];

                                if (isset($values[$locale][$key['name']])) {
                                    $currentProject['values'][$locale][$key['name']] = $values[$locale][$key['name']];
                                }
                            }
                        }
                    }

                    $values = $currentProject['values'];

                    break;

                case 'override':
                default:
                    $this->dataStorage->remove('lokalize/projects', ['_id' => $project['_id']]);
                    $this->dataStorage->insert('lokalize/projects', $project);
                    break;
            }

            $project['keys'] = $keys;
            $project['values'] = $values;

            $this->dataStorage->save('lokalize/projects', $project);
        }

        return ['success' => true];
    },

    'sync:pull' => function(array $settings = [], ?array $target = null, ?Client $client = null) {

        $settings = array_merge([
            'syncAll' => true,
            'projects' => [],
            'mode' => 'override',
        ], $settings);

        $run = 0;

        while (true) {

            $response = $client->request('POST', 'api/sync/job', [
                'json' => [
                    'job' => 'lokalize',
                    'mode' => 'pull',
                    'payload' => $this->helper('jwt')->encode([
                        'projects' => $settings['syncAll'] ? [] : $settings['projects'],
                        'mode' => $settings['mode'],
                        'run' => $run
                    ], $target['syncKey'])
                ]
            ]);

            $payload = json_decode($response->getBody()->getContents(), true);

            if (!isset($payload['projects']) || !count($payload['projects'])) {
                return true;
            }

            $mode = $settings['mode'] ?? 'override';

            foreach ($payload['projects'] as $project) {

                $currentMode = $mode;
                $currentProject = $this->dataStorage->findOne('lokalize/projects', ['_id' => $project['_id']]);

                if (!$currentProject) {
                    $currentMode = 'override';
                }

                // prevent mongodb error: no `.` allowed in field names on insert
                $keys = $project['keys'];
                $values = $project['values'];

                unset($project['keys'], $project['values']);

                switch ($currentMode) {
                    case 'missingKeys':

                        // add missing keys
                        $keysCurrent = [];
                        $localsCurrent = [];

                        // sync keys
                        foreach ($currentProject['keys'] as $key) {
                            $keysCurrent[] = $key['name'];
                        }

                        foreach ($keys as $key) {
                            if (!in_array($key['name'], $keysCurrent)) $currentProject['keys'][] = $key;
                        }

                        $keys = $currentProject['keys'];

                        // sync locales
                        foreach ($currentProject['locales'] as $locale) {
                            $localsCurrent[] = $locale['i18n'];
                        }

                        foreach ($project['locales'] as $locale) {
                            if (!in_array($locale['i18n'], $localsCurrent)) $currentProject['locales'][] = $locale;
                        }

                        $project['locales'] = $currentProject['locales'];

                        // add missing values
                        foreach ($project['locales'] as $locale) {

                            $locale = $locale['i18n'];

                            if (!isset($currentProject['values'][$locale])) {
                                $currentProject['values'][$locale] = [];
                            }

                            foreach ($keys as $key) {

                                if (!isset($currentProject['values'][$locale][$key['name']])) {
                                    $currentProject['values'][$locale][$key['name']] = ['value' => null];

                                    if (isset($values[$locale][$key['name']])) {
                                        $currentProject['values'][$locale][$key['name']] = $values[$locale][$key['name']];
                                    }
                                }
                            }
                        }

                        $values = $currentProject['values'];

                        break;
                    case 'override':
                    default:
                        $this->dataStorage->remove('lokalize/projects', ['_id' => $project['_id']]);
                        $this->dataStorage->insert('lokalize/projects', $project);
                        break;
                }

                $project['keys'] = $keys;
                $project['values'] = $values;

                $this->dataStorage->save('lokalize/projects', $project);
            }

            $run += 1;
        }
    },

    'on:pull' => function($payload = null) {

        $run = $payload['run'] ?? 0;
        $limit = 20;

        $filter = null;

        if (!$payload['projects'] && count($payload['projects'])) {
            $filter = ['name' => ['$in' => $payload['projects']]];
        }

        $projects = $this->dataStorage->find('lokalize/projects', [
            'filter' => $filter,
            'skip' => $run * $limit,
            'limit' => $limit
        ])->toArray();

        $payload = [
            'projects' => $projects
        ];

        return $payload;
    }
];
