<?php

use App\Translation;
use Illuminate\Support\Arr;
use Illuminate\Database\Seeder;
use Illuminate\Filesystem\Filesystem;

class TranslationSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $this->loadLocaleDirectories( resource_path('lang') );
    }

    public function loadLocaleDirectories($path, $namespace = '*')
    {
        $files = new Filesystem;
        $availableLocales = array_keys(config('app.locales'));
        $directories      = $files->directories($path);
        foreach ($directories as $directory) {
            $locale = basename($directory);
            if (in_array($locale, $availableLocales)) {
                $this->loadDirectory($directory, $locale, $namespace);
            }
            if ($locale === 'vendor' && $namespace === '*') {
                $this->loadVendor($directory);
            }
        }
    }

    public function loadVendor($path)
    {
        $files       = new Filesystem;
        $directories = $files->directories($path);
        foreach ($directories as $directory) {
            $namespace = basename($directory);
            $this->loadLocaleDirectories($directory, $namespace);
        }
    }

    public function loadDirectory($path, $locale, $namespace = '*', $group = '')
    {
        // Load all files inside subdirectories:
        $files = new Filesystem;
        $directories = $files->directories($path);
        foreach ($directories as $directory) {
            $directoryName = str_replace($path . '/', '', $directory);
            $dirGroup      = $group . basename($directory) . '/';
            $this->loadDirectory($directory, $locale, $namespace, $dirGroup);
        }

        // Load all files in root:
        $files = $files->files($path);
        foreach ($files as $file) {
            $this->loadFile($file, $locale, $namespace, $group);
        }
    }

    public function loadFile($file, $locale, $namespace = '*', $group = '')
    {
        $files = new Filesystem;
        $group = $group . basename($file, '.php');

        if ($group !== 'index') {
            $translations = $files->getRequire($file);
            $this->loadArray($translations, $locale, $group, $namespace, $locale == config('app.locale'));
        }
    }

    public function loadArray(array $lines, $locale, $group, $namespace = '*')
    {
        // Transform the lines into a flat dot array:
        $lines = Arr::dot($lines);
        foreach ($lines as $item => $text) {
            if (is_string($text)) {
                // Check if the entry exists in the database:
                $translation = Translation::whereLocale($locale)
                    ->whereNamespace($namespace)
                    ->whereGroup($group)
                    ->whereItem($item)
                    ->first();

                // If the translation already exists, we update the text:
                if ($translation && !$translation->isLocked()) {
                    $translation->text = $text;
                    $saved             = $translation->save();
                    if ($saved && $translation->locale === $this->defaultLocale) {
                        $this->flagAsUnstable($namespace, $group, $item);
                    }
                }
                // If no entry was found, create it:
                else {
                    $this->create(compact('locale', 'namespace', 'group', 'item', 'text'));
                }
            }
        }
    }

    public function flagAsUnstable($namespace, $group, $item)
    {
        Translation::whereNamespace($namespace)
                    ->whereGroup($group)
                    ->whereItem($item)
                    ->where('locale', '!=', $this->defaultLocale)
                    ->update(['unstable' => '1']);
    }

    public function create(array $attributes)
    {
        return $this->validate($attributes) ? Translation::create($attributes) : null;
    }

    public function validate(array $attributes)
    {
        $table     = (new Translation())->getTable();
        $locale    = Arr::get($attributes, 'locale', '');
        $namespace = Arr::get($attributes, 'namespace', '');
        $group     = Arr::get($attributes, 'group', '');
        $rules     = [
            'locale'    => 'required',
            'namespace' => 'required',
            'group'     => 'required',
            'item'      => "required|unique:{$table},item,NULL,id,locale,{$locale},namespace,{$namespace},group,{$group}",
            'text'      => '', // Translations may be empty
        ];
        $validator = app()->validator->make($attributes, $rules);
        if ($validator->fails()) {
            $this->errors = $validator->errors();
            return false;
        }
        return true;
    }
}
