<?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();
        });

        DB::insert("insert into goliath_regions (name, visible) values ('Oceania', 1), ('Asia-Pacific', 1), ('America', 1), ('EMEA', 1);");

        DB::insert("insert into goliath_subregions (name, region_id, visible) values ('Brisbane', 1, 1), ('Sydney', 1, 1), ('Melbourne', 1, 1), ('Adelaide', 1, 1), ('Perth', 1, 1), ('Auckland', 1, 1);");
        
        DB::insert("insert into goliath_subregions (name, region_id, visible) values ('Singapore', 2, 1), ('Malaysia', 2, 1), ('Hong Kong', 2, 1), ('Taiwan', 2, 1), ('Tokyo', 2, 1), ('Seoul', 2, 1), ('Philipines', 2, 1);");
        
        DB::insert("insert into goliath_subregions (name, region_id, visible) values ('Los Angeles', 3, 1), ('Phoenix', 3, 1), ('Dallas', 3, 1), ('Atlanta', 3, 1), ('Ashburn', 3, 1), ('New York', 3, 0), ('Chicago', 3, 1), ('Seattle', 3, 1);");
        
        DB::insert("insert into goliath_subregions (name, region_id, visible) values ('London', 4, 1), ('Amsterdam', 4, 1), ('Frankfurt', 4, 1), ('Paris', 4, 1), ('Madrid', 4, 1), ('Marseille', 4, 0), ('Milan', 4, 1), ('Sofia', 4, 1), ('Warsaw', 4, 1), ('Helsinki', 4, 1);");
        
        DB::insert("insert into goliath_metro (name, subregion_id, visible) values ('Coresite', (select id from goliath_subregions where name = 'Los Angeles'), 1), ('Equinix', (select id from goliath_subregions where name = 'Los Angeles'), 1), ('Equinix', (select id from goliath_subregions where name = 'New York'), 1), ('165 Halsey', (select id from goliath_subregions where name = 'New York'), 1), ('Telehouse North', (select id from goliath_subregions where name = 'London'), 1), ('Telehouse West', (select id from goliath_subregions where name = 'London'), 1), ('Slough', (select id from goliath_subregions where name = 'London'), 1), ('Equinix', (select id from goliath_subregions where name = 'Amsterdam'), 1), ('Nikhef', (select id from goliath_subregions where name = 'Amsterdam'), 1), ('Telehouse', (select id from goliath_subregions where name = 'Paris'), 1), ('Equinix', (select id from goliath_subregions where name = 'Paris'), 1), ('Equinix', (select id from goliath_subregions where name = 'Warsaw'), 1), ('LIM', (select id from goliath_subregions where name = 'Warsaw'), 1), ('TY8', (select id from goliath_subregions where name = 'Tokyo'), 1), ('TY15', (select id from goliath_subregions where name = 'Tokyo'), 1);");

        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');
    }
}
