<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class GoliathSetup extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('goliath_regions', function (Blueprint $table) {
            $table->id();
            $table->string('name')->nullable();
            $table->tinyInteger('visible')->default(0);
        });

        Schema::create('goliath_subregions', function (Blueprint $table) {
            $table->id();
            $table->string('name')->nullable();
            $table->tinyInteger('visible')->default(0);
            $table->foreignId('region_id')->cascadeOnDelete()->constrained('goliath_regions')->nullable();
        });
        
        Schema::create('goliath_metro', function (Blueprint $table) {
            $table->id();
            $table->string('name')->nullable();
            $table->tinyInteger('visible')->default(0);
            $table->foreignId('subregion_id')->cascadeOnDelete()->constrained('goliath_subregions')->nullable();
        });

        Schema::create('goliath_chain_types', function (Blueprint $table) {
            $table->id();
            $table->string('name')->nullable();
        });

        DB::table('goliath_chain_types')->insert([[
            'name' => 'Universal'
        ], [
            'name' => 'Specific'
        ], [
            'name' => 'Reusable'
        ], [
            'name' => 'Marketable - Template'
        ], [
            'name' => 'Marketable - Specific'
        ]]);

        Schema::create('goliath_match_types', function (Blueprint $table) {
            $table->id();
            $table->string('system_name')->nullable();
            $table->string('human_name')->nullable();
        });

        DB::table('goliath_match_types')->insert([[
            'system_name' => 'bpf',
            'human_name' => 'BPF'
        ], [
            'system_name' => 'filter',
            'human_name' => 'Filter'
        ]]);

        Schema::create('goliath_action_types', function (Blueprint $table) {
            $table->id();
            $table->string('system_name')->nullable();
            $table->string('human_name')->nullable();
        });

        DB::table('goliath_action_types')->insert([[
            'system_name' => 'accept',
            'human_name' => 'Accept'
        ], [
            'human_name' => 'Drop',
            'system_name' => 'drop'
        ], [
            'human_name' => 'Rate Limit',
            'system_name' => 'police'
        ], [
            'human_name' => 'Goto Other Chain',
            'system_name' => 'goto'
        ]]);

        Schema::create('goliath_appliances', function (Blueprint $table) {
            // General characteristics - PK, timestamps, soft-deletable
            $table->id();
            $table->timestamps();
            $table->softDeletes();

            // Foreign identifiers
            $table->foreignId('organisation_id')->cascadeOnDelete()->constrained('organisations');
            $table->foreignId('region_id')->cascadeOnDelete()->nullable()->constrained('goliath_regions');
            $table->foreignId('subregion_id')->cascadeOnDelete()->nullable()->constrained('goliath_subregions');
            $table->foreignId('metro_id')->cascadeOnDelete()->nullable()->constrained('goliath_metro');

            // Characteristics
            $table->string('name')->nullable();
            $table->string('location')->nullable();
            $table->string('cpu')->nullable();
            $table->string('nic')->nullable();

            $table->ipAddress('address');

            $table->string('status')->nullable();
            $table->string('hash')->nullable();
            
            $table->tinyInteger('authorised')->nullable();
            $table->timestamp('booted_at')->nullable();
            $table->timestamp('registered_at')->nullable();
        });

        Schema::create('goliath_appliance_messages', function (Blueprint $table) {
            // General characteristics - PK, timestamps, soft-deletable
            $table->id();
            $table->timestamps();

            // Foreign identifiers
            $table->foreignId('appliance_id')->cascadeOnDelete()->constrained('goliath_appliances');

            // Characteristics
            $table->string('message')->nullable();
            
            // Flags
            $table->tinyInteger('processed')->nullable();
        });

        Schema::create('chain_element_matches', function (Blueprint $table) {
            // General characteristics - PK, timestamps, soft-deletable
            $table->id();
            $table->timestamps();
            $table->softDeletes();
    
            // Foreign identifiers
            $table->foreignId('author_id')->cascadeOnDelete()->constrained('organisations');
            $table->foreignId('match_type_id')->cascadeOnDelete()->constrained('goliath_match_types');
    
            // Characteristics
            $table->string('name')->nullable();
            $table->string('bpf')->nullable();
            
            $table->tinyInteger('private')->nullable();
        });

        Schema::create('chain_element_actions', function (Blueprint $table) {
            // General characteristics - PK, timestamps, soft-deletable
            $table->id();
            $table->timestamps();
            $table->softDeletes();
    
            // Foreign identifiers
            $table->foreignId('organisation_id')->cascadeOnDelete()->constrained('organisations');    
            $table->foreignId('action_type_id')->cascadeOnDelete()->constrained('goliath_action_types')->nullable();

            $table->bigInteger('pps_limit')->nullable();
            $table->bigInteger('bitrate')->nullable();
        });

        Schema::create('chains', function (Blueprint $table) {
            // General characteristics - PK, timestamps, soft-deletable
            $table->id();
            $table->timestamps();
            $table->softDeletes();
            $table->uuid('uuid');
    
            // Foreign identifiers
            $table->foreignId('organisation_id')->cascadeOnDelete()->constrained('organisations');
            $table->foreignId('chain_type_id')->cascadeOnDelete()->constrained('goliath_chain_types');

            // Wizbiz for aesthetics
            $table->bigInteger('default_x')->nullable();
            $table->bigInteger('default_y')->nullable();

            // Characteristics
            $table->string('name')->nullable();
        });

        Schema::create('chain_elements', function (Blueprint $table) {
            // General characteristics - PK, timestamps, soft-deletable
            $table->id();
            $table->timestamps();
            $table->softDeletes();

            $table->smallInteger('position')->nullable();

            // Aesthetics
            $table->bigInteger('x')->nullable();
            $table->bigInteger('y')->nullable();
    
            // Foreign identifiers
            $table->foreignId('chain_id')->cascadeOnDelete()->constrained('chains')->nullable();
            $table->foreignId('match_id')->cascadeOnDelete()->constrained('chain_element_matches')->nullable();
        });

        Schema::create('chain_element_outcomes', function (Blueprint $table) {
            // General characteristics - PK, timestamps, soft-deletable
            $table->id();
            $table->timestamps();
            $table->softDeletes();
    
            // Foreign identifiers
            $table->foreignId('chain_id')->casecadeOnDelete()->constrained('chains'); // Point at the origin chain...
            $table->foreignId('element_id')->cascadeOnDelete()->nullable()->constrained('chain_elements'); // Nullable to allow default outcomes
            $table->foreignId('pass_chain_id')->cascadeOnDelete()->nullable()->constrained('chains');
            $table->foreignId('pass_action_id')->cascadeOnDelete()->nullable()->constrained('chain_element_actions');

            // Simple goto next element
            $table->tinyInteger('goto_next_element');
        });

        Schema::create('prefix_goliath_firewall', function (Blueprint $table) {
            // General characteristics - PK, timestamps, soft-deletable
            $table->id();
            $table->timestamps();
            $table->softDeletes();
    
            // Foreign identifiers
            $table->foreignId('prefix_id')->cascadeOnDelete()->constrained('prefixes');
            $table->foreignId('chain_id')->cascadeOnDelete()->nullable()->constrained('chains');
            
            $table->foreignId('region_id')->cascadeOnDelete()->nullable()->constrained('goliath_regions');
            $table->foreignId('subregion_id')->cascadeOnDelete()->nullable()->constrained('goliath_subregions');
            $table->foreignId('metro_id')->cascadeOnDelete()->nullable()->constrained('goliath_metro');
        });
    }

    public function down()
    {
        Schema::dropIfExists('prefix_goliath_firewall');
        Schema::dropIfExists('chain_element_outcomes');
        Schema::dropIfExists('chain_elements');
        Schema::dropIfExists('chains');
        Schema::dropIfExists('chain_element_actions');
        Schema::dropIfExists('chain_element_matches');
        Schema::dropIfExists('goliath_appliance_messages');
        Schema::dropIfExists('goliath_appliances');
        Schema::dropIfExists('goliath_action_types');
        Schema::dropIfExists('goliath_match_types');
        Schema::dropIfExists('goliath_chain_types');
        Schema::dropIfExists('goliath_metro');
        Schema::dropIfExists('goliath_subregions');
        Schema::dropIfExists('goliath_regions');
    }
}
