<?php

namespace App\Http\Controllers;

use App\AlbumDefaultAnonymousPermission;
use App\Configuration;
use App\Facade\UserConfig;
use App\Helpers\MiscHelper;
use App\Http\Requests\StoreUserRequest;
use App\Permission;
use App\Storage;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;

class InstallController extends Controller
{
    public function administrator(StoreUserRequest $request)
    {
        // Validate we're at the required stage
        $stage = 2;
        if (intval($request->session()->get('install_stage')) < $stage)
        {
            return redirect(route('install.database'));
        }

        // If we already have an admin account, this step can be skipped
        $canSkip = User::where('is_admin', true)->count() > 0;
        
        if ($canSkip && $request->has('skip'))
        {
            return $this->completeSetup();
        }

        if ($request->method() == 'POST')
        {
            $user = new User();
            $user->name = $request->get('name');
            $user->email = $request->get('email');
            $user->password = bcrypt($request->get('password'));
            $user->is_admin = true;
            $user->is_activated = true;
            $user->enable_profile_page = true;
            $user->save();

            return $this->completeSetup();
        }

        return view('install.administrator', [
            'can_skip' => $canSkip
        ]);
    }

    public function database(Request $request)
    {
        // This is the first installation step therefore it doesn't need to verify the stage

        if ($request->method() == 'POST')
        {
            $baseDirectory = dirname(dirname(dirname(__DIR__)));

            $data = [
                sprintf('APP_KEY=%s', config('app.key')),
                'DB_CONNECTION=mysql',
                sprintf('DB_HOST=%s', $request->get('mysql-server')),
                sprintf('DB_PORT=%s', intval($request->get('mysql-port'))),
                sprintf('DB_DATABASE=%s', $request->get('mysql-database')),
                sprintf('DB_USERNAME=%s', $request->get('mysql-username')),
                sprintf('DB_PASSWORD=%s', $request->get('mysql-password'))
            ];
            file_put_contents(sprintf('%s/.env', $baseDirectory), join(PHP_EOL, $data) . PHP_EOL);

            // Update the in-memory configuration ready for Artisan :)
            $configData = [
                'connections' => [
                    'mysql' => [
                        'driver' => 'mysql',
                        'host' => $request->get('mysql-server'),
                        'port' => intval($request->get('mysql-port')),
                        'database' => $request->get('mysql-database'),
                        'username' => $request->get('mysql-username'),
                        'password' => $request->get('mysql-password')
                    ]
                ]
            ];
            config(['database' => array_replace_recursive(config('database'), $configData)]);

            try
            {
                DB::reconnect();

                Artisan::call('cache:clear');
                Artisan::call('migrate', ['--force' => true]);
                Artisan::call('db:seed', ['--force' => true]);

                $versionNumber = UserConfig::getOrCreateModel('app_version');
                $versionNumber->value = config('app.version');
                $versionNumber->save();

                // Default settings
                $this->setConfigurationForNewSystems();

                $request->session()->put('install_stage', 2);
                return redirect(route('install.administrator'));
            }
            catch (\Exception $ex)
            {
                $request->session()->flash('database_error', $ex->getMessage());
                return redirect(route('install.database'))
                    ->withInput($request->input());
            }
        }

        return view('install.database', [
            'database_error' => $request->session()->get('database_error')
        ]);
    }

    private function completeSetup()
    {
        // Flag as installed
        MiscHelper::setEnvironmentSetting('APP_INSTALLED', true);

        // Switch to database sessions (more reliable)
        MiscHelper::setEnvironmentSetting('SESSION_DRIVER', 'database');

        // Add an internal storage if it doesn't already exist
        $this->createInternalStorageLocationIfNotExist();

        // Skip forward. If you go past Go, collect £200!
        return redirect(route('home', ['install_completed' => true]));
    }

    private function createInternalStorageLocationIfNotExist()
    {
        $storage = Storage::where('is_internal', true)->first();
        if (is_null($storage))
        {
            $location = sprintf('%s/storage/app/albums', dirname(dirname(dirname(__DIR__))));

            $storage = new Storage();
            $storage->name = trans('installer.default_storage_name');
            $storage->is_active = true;
            $storage->is_default = true;
            $storage->is_internal = true;
            $storage->location = $location;
            $storage->source = 'LocalFilesystemSource';
            $storage->save();

            // Try and create the physical location
            if (!file_exists($location))
            {
                @mkdir($location);
            }
        }
    }

    private function setDefaultAnonymousPermission($section, $permission)
    {
        $permission = Permission::where([
            ['section', $section],
            ['description', $permission]
        ])->first();

        if (is_null($permission))
        {
            return;
        }

        $adap = new AlbumDefaultAnonymousPermission();
        $adap->permission_id = $permission->id;
        $adap->save();
    }

    private function setConfigurationForNewSystems()
    {
        /** @var Configuration $socialFeeds */
        $socialFeeds = UserConfig::getOrCreateModel('social_user_feeds');
        $socialFeeds->value = true;
        $socialFeeds->save();

        /** @var Configuration $socialProfiles */
        $socialProfiles = UserConfig::getOrCreateModel('social_user_profiles');
        $socialProfiles->value = true;
        $socialProfiles->save();

        /** @var Configuration $photoComments */
        $photoComments = UserConfig::getOrCreateModel('allow_photo_comments');
        $photoComments->value = true;
        $photoComments->save();

        $defaultPermissions = ['album.list', 'album.view', 'album.post-comment'];
        foreach ($defaultPermissions as $defaultPermission)
        {
            $permissionParts = explode('.', $defaultPermission);

            $this->setDefaultAnonymousPermission($permissionParts[0], $permissionParts[1]);
        }
    }
}