<?php

namespace App;

use App\Builders\EntityDefinitionBuilder;
use DB;
use Illuminate\Database\Eloquent\Collection;

use Illuminate\Database\Eloquent\Model;
use Log;

/**
 * Class EntityClass
 *
 * !! WARNING !!
 * Constants & methods within this class are designed for only in initial Database seeding!
 *
 * You can't count on those IDs to be preserved as those values are allowed to be deleted / created ...
 *
 * @package App
 */
class EntityClassInitialSetup
{

    const FIRST_DEVICE_CLASS_ID = self::SERVER_ID;

    const SERVER = 'Server';
    const SERVER_ID = 1;

    const RAID = 'RAID';
    const RAID_ID = 2;

    const DISC = 'Disc';
    const DISC_ID = 3;

    const PROCESSOR = 'Processor';
    const PROCESSOR_ID = 4;

    const DISC_CONTROLLER = 'Disc Controller';
    const DISC_CONTROLLER_ID = 5;

    const MOTHERBOARD = 'Motherboard';
    const MOTHERBOARD_ID = 6;

    const NETWORK_CARD = 'Network Card';
    const NETWORK_CARD_ID = 7;

    const TRANSCEIVER = 'Transceiver';
    const TRANSCEIVER_ID = 8;

    const SWITCH = 'Switch';
    const SWITCH_ID = 9;

    const FAN = 'Fan';
    const FAN_ID = 10;

    const MODULE = 'Module';
    const MODULE_ID = 11;

    const POWER_SUPPLY = 'Power Supplier';
    const POWER_SUPPLY_ID = 12;

    const WIFI_AP = 'WiFi AP';
    const WIFI_AP_ID = 13;

    const VLAN = 'VLAN';
    const VLAN_ID = 14;

    /**
     * Newly added start here
     */

    const WIFI_ACCOUNT_LOCATIONS = 'WiFi Account Locations';
    const WIFI_ACCOUNT_LOCATIONS_ID = 15;

    const WIFI_ACCOUNT = 'WiFi Account';
    const WIFI_ACCOUNT_ID = 16;

    const WEB_PAGE = 'Web Page';
    const WEB_PAGE_ID = 17;

    const INSTITUTE = 'Institute';
    const INSTITUTE_ID = 18;

    const EMPLOYEE = 'Employee';
    const EMPLOYEE_ID = 19;

    const SERVER_USER = 'Server User';
    const SERVER_USER_ID = 20;

    const GROUP_MEMBERSHIP = 'Server Group Membership';
    const GROUP_MEMBERSHIP_ID = 21;

    //const SERVER_GROUP = 'Server Group';
    //const SERVER_GROUP_ID = 22;

    const LAST_DEVICE_CLASS_ID = self::GROUP_MEMBERSHIP_ID;
    /**
     * Stop list non-type
     */
    const FIRST_DEVICE_CLASS_TYPE_ID = self::DISC_TYPE_ID;

    const DISC_TYPE = 'Disc Type';
    const DISC_TYPE_ID = 23;

    const PROCESSOR_TYPE = 'Processor Type';
    const PROCESSOR_TYPE_ID = 24;

    const DISC_CONTROLLER_TYPE = 'Disc Controller Type';
    const DISC_CONTROLLER_TYPE_ID = 25;

    const MOTHERBOARD_TYPE = 'Motherboard Type';
    const MOTHERBOARD_TYPE_ID = 26;

    const NETWORK_CARD_TYPE = 'Network Card Type';
    const NETWORK_CARD_TYPE_ID = 27;

    const WIFI_PLATFORM = 'WiFi Platform';
    const WIFI_PLATFORM_ID = 28;

    /**
     * Newly added start here
     */

    const SERVER_TYPE = 'Server Type';
    const SERVER_TYPE_ID = 29;

    const SWITCH_TYPE = 'Switch Type';
    const SWITCH_TYPE_ID = 30;

    const FAN_TYPE = 'Fan Type';
    const FAN_TYPE_ID = 31;

    const POWER_SUPPLY_TYPE = 'Power Supplier Type';
    const POWER_SUPPLY_TYPE_ID = 32;

    const TRANSCEIVER_TYPE = 'Transceiver Type';
    const TRANSCEIVER_TYPE_ID = 33;

    const SERVER_GROUP = 'Server Group';
    //const SERVER_GROUP_ID = 19;
    const SERVER_GROUP_ID = 34;

    const MODULE_TYPE = 'Module Type';
    const MODULE_TYPE_ID = 35;

    const LAST_DEVICE_CLASS_TYPE_ID = self::MODULE_TYPE_ID;


    /**
     * Returns appropriate entity definition according to provided entity class name
     *
     * @param $entityClassName
     * @return array
     * @throws \Exception
     */
    public static function getEntityDefinition($entityClassName)
    {
        switch ($entityClassName) {
            case EntityClassInitialSetup::SERVER:
                return self::serverDefinition();
                break;
            case EntityClassInitialSetup::SERVER_TYPE:
                return self::serverTypeDefinition();
                break;
            case EntityClassInitialSetup::RAID:
                return self::raidDefinition();
                break;
            case EntityClassInitialSetup::DISC:
                return self::discDefinition();
                break;
            case EntityClassInitialSetup::DISC_TYPE:
                return self::discTypeDefinition();
                break;
            case EntityClassInitialSetup::PROCESSOR:
                return self::processorDefinition();
                break;
            case EntityClassInitialSetup::PROCESSOR_TYPE:
                return self::processorTypeDefinition();
                break;
            case EntityClassInitialSetup::DISC_CONTROLLER:
                return self::discControllerDefinition();
                break;
            case EntityClassInitialSetup::DISC_CONTROLLER_TYPE:
                return self::discControllerTypeDefinition();
                break;
            case EntityClassInitialSetup::MOTHERBOARD:
                return self::motherboardDefinition();
                break;
            case EntityClassInitialSetup::MOTHERBOARD_TYPE:
                return self::motherboardTypeDefinition();
                break;
            case EntityClassInitialSetup::NETWORK_CARD:
                return self::networkCardDefinition();
                break;
            case EntityClassInitialSetup::NETWORK_CARD_TYPE:
                return self::networkCardTypeDefinition();
                break;
            case EntityClassInitialSetup::TRANSCEIVER:
                return self::transceiverDefinition();
                break;
            case EntityClassInitialSetup::TRANSCEIVER_TYPE:
                return self::transceiverTypeDefinition();
                break;
            case EntityClassInitialSetup::SWITCH:
                return self::switchDefinition();
                break;
            case EntityClassInitialSetup::SWITCH_TYPE:
                return self::switchTypeDefinition();
                break;
            case EntityClassInitialSetup::FAN:
                return self::fanDefinition();
                break;
            case EntityClassInitialSetup::FAN_TYPE:
                return self::fanTypeDefinition();
                break;
            case EntityClassInitialSetup::MODULE:
                return self::moduleDefinition();
                break;
            case EntityClassInitialSetup::MODULE_TYPE:
                return self::moduleTypeDefinition();
                break;
            case EntityClassInitialSetup::POWER_SUPPLY:
                return self::powerSupplyDefinition();
                break;
            case EntityClassInitialSetup::POWER_SUPPLY_TYPE:
                return self::powerSupplyTypeDefinition();
                break;
            case EntityClassInitialSetup::WIFI_AP:
                return self::wifiApDefinition();
                break;
            case EntityClassInitialSetup::WIFI_PLATFORM:
                return self::wifiPlatformDefinition();
                break;
            case EntityClassInitialSetup::VLAN:
                return self::vLanDefinition();
                break;
            case EntityClassInitialSetup::WIFI_ACCOUNT:
                return self::wifiAccountDefinition();
                break;
            case EntityClassInitialSetup::WIFI_ACCOUNT_LOCATIONS:
                return self::wifiAccountLocationDefinition();
                break;
            case EntityClassInitialSetup::SERVER_USER:
                return self::serverUserDefinition();
                break;
            case EntityClassInitialSetup::GROUP_MEMBERSHIP:
                return self::groupMembershipDefinition();
                break;
            case EntityClassInitialSetup::SERVER_GROUP:
                return self::serverGroupDefinition();
                break;
            case EntityClassInitialSetup::WEB_PAGE:
                return self::webPageDefinition();
                break;
            case EntityClassInitialSetup::INSTITUTE:
                return self::instituteDefinition();
                break;
            case EntityClassInitialSetup::EMPLOYEE:
                return self::employeeDefinition();
                break;
            default:
                $message = "Unrecognized EntityClass '" . $entityClassName . "' !";
                Log::error($message);
                throw new \Exception($message);
        }
    }

    /**
     * Builds an parameter definition
     *
     * @param bool $required
     * @param string $parameterType
     * @param int $maxParamLenOrVal
     * @return array
     * @throws \Exception
     */
    protected static function buildParam($required, $parameterType, $maxParamLenOrVal = null)
    {
        // Set default VARCHAR length
        if (
            $parameterType === EntityParameter::STRING &&
            (
                $maxParamLenOrVal === null ||
                $maxParamLenOrVal > EntityParameter::STRING_DB_LEN
            )
        ) {
            $maxParamLenOrVal = EntityParameter::STRING_DB_LEN;
        }

        // Effective SQL Injection prevention (although it would have to be from within the code, not user input :D)
        if (array_search($parameterType, EntityParameter::ALL_PARAMETERS) === false)
            throw new \Exception("Unrecognized parameter type '$parameterType'!");

        return [
            'required' => $required,
            'parameter_type_id' => DB::raw("(SELECT id FROM parameter_datatypes WHERE name = '$parameterType')"),
            'max_param_len_or_val' => $maxParamLenOrVal
        ];
    }

    /**
     * Builds an parameter definition
     *
     * @param bool $required
     * @param string $parameterType
     * @param int $maxParamLenOrVal
     * @return array
     */
    protected static function buildUniqueParam($required, $parameterType, $maxParamLenOrVal = null)
    {
        $definition = self::buildParam($required, $parameterType, $maxParamLenOrVal);
        $definition['unique'] = true;

        return $definition;
    }


    /**
     * Returns server entity class definition.
     *
     * @return array
     */
    public static function serverDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::SERVER_ID, EntityClassInitialSetup::SERVER))
            ->parameters([
                'name' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 20),
                'ram_size_mb' =>
                    self::buildParam(false, EntityParameter::INT),
                'sap_number' =>
                    self::buildUniqueParam(false, EntityParameter::INT),
            ])
            ->parentClassIds([EntityClassInitialSetup::RAID_ID => [EntityClass::PARENT_MUST_NOT_HAVE_PARENT_CONSTRAINT]], false)
            ->entityTypeId(self::SERVER_TYPE_ID)
            ->hasManufacturer()
            ->hasSupplier()
            ->hasLocation()
            ->finish();
    }

    /**
     * Returns server_type entity class definition.
     *
     * @return array
     */
    public static function serverTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::SERVER_TYPE_ID, EntityClassInitialSetup::SERVER_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns raid entity class definition.
     *
     * @return array
     */
    public static function raidDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::RAID_ID, EntityClassInitialSetup::RAID))
            ->parameters([
                'raid_type' =>
                    self::buildParam(true, EntityParameter::TINY_INT, 10),
                'software_raid' =>
                    self::buildParam(true, EntityParameter::TINY_INT, 1)
            ])
            ->parentClassIds([EntityClassInitialSetup::SERVER_ID], false)
            ->hasManufacturer()
            ->finish();
    }

    /**
     * Returns disc entity class definition.
     *
     * @return array
     */
    public static function discDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::DISC_ID, EntityClassInitialSetup::DISC))
            ->entityTypeId(EntityClassInitialSetup::DISC_TYPE_ID)
            ->parentClassIds([EntityClassInitialSetup::RAID_ID], true)
            ->hasSupplier()
            ->finish();
    }

    /**
     * Returns disc_type entity class definition.
     *
     * @return array
     */
    public static function discTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::DISC_TYPE_ID, EntityClassInitialSetup::DISC_TYPE))
            ->parameters([
                'type' =>
                    self::buildParam(false, EntityParameter::STRING),
                'ssd' =>
                    self::buildParam(true, EntityParameter::TINY_INT, 1),
                'size_gb' =>
                    self::buildParam(true, EntityParameter::INT)
            ])
            ->isType()
            ->hasManufacturer()
            ->finish();
    }

    /**
     * Returns processor entity class definition.
     *
     * @return array
     */
    public static function processorDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::PROCESSOR_ID, EntityClassInitialSetup::PROCESSOR))
            ->parentClassIds([EntityClassInitialSetup::SERVER_ID], true)
            ->entityTypeId(EntityClassInitialSetup::PROCESSOR_TYPE_ID)
            ->finish();
    }

    /**
     * Returns processor_type entity class definition.
     *
     * @return array
     */
    public static function processorTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::PROCESSOR_TYPE_ID, EntityClassInitialSetup::PROCESSOR_TYPE))
            ->parameters([
                'name' =>
                    self::buildParam(true, EntityParameter::STRING),
                'frequency_mhz' =>
                    self::buildParam(true, EntityParameter::INT),
                'cores_count' =>
                    self::buildParam(true, EntityParameter::TINY_INT)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns disc_controller entity class definition.
     *
     * @return array
     */
    public static function discControllerDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::DISC_CONTROLLER_ID, EntityClassInitialSetup::DISC_CONTROLLER))
            ->parentClassIds([EntityClassInitialSetup::SERVER_ID], true)
            ->entityTypeId(EntityClassInitialSetup::DISC_CONTROLLER_TYPE_ID)
            ->finish();
    }

    /**
     * Returns disc_controller_type entity class definition.
     *
     * @return array
     */
    public static function discControllerTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::DISC_CONTROLLER_TYPE_ID, EntityClassInitialSetup::DISC_CONTROLLER_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns motherboard entity class definition.
     *
     * @return array
     */
    public static function motherboardDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::MOTHERBOARD_ID, EntityClassInitialSetup::MOTHERBOARD))
            ->parameters([
                'name' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 45),
            ])
            ->parentClassIds([EntityClassInitialSetup::SERVER_ID], true)
            ->entityTypeId(EntityClassInitialSetup::MOTHERBOARD_TYPE_ID)
            ->finish();
    }

    /**
     * Returns motherboard_type entity class definition.
     *
     * @return array
     */
    public static function motherboardTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::MOTHERBOARD_TYPE_ID, EntityClassInitialSetup::MOTHERBOARD_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns network entity class definition.
     *
     * @return array
     */
    public static function networkCardDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::NETWORK_CARD_ID, EntityClassInitialSetup::NETWORK_CARD))
            ->parentClassIds([EntityClassInitialSetup::SERVER_ID], true)
            ->entityTypeId(EntityClassInitialSetup::NETWORK_CARD_TYPE_ID)
            ->finish();
    }

    /**
     * Returns network_card_type entity class definition.
     *
     * @return array
     */
    public static function networkCardTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::NETWORK_CARD_TYPE_ID, EntityClassInitialSetup::NETWORK_CARD_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING),

                'bandwidth_mb' =>
                    self::buildParam(false, EntityParameter::INT),

                'network_interface' =>
                    self::buildParam(true, EntityParameter::INT)
            ])
            ->isType()
            ->hasManufacturer()
            ->finish();
    }

    /**
     * Returns transceiver entity class definition.
     *
     * @return array
     */
    public static function transceiverDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::TRANSCEIVER_ID, EntityClassInitialSetup::TRANSCEIVER))
            ->parameters([
                'description' =>
                    self::buildParam(true, EntityParameter::STRING),
                'serial_number' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 65)
            ])
            ->parentClassIds([EntityClassInitialSetup::SWITCH_ID, EntityClassInitialSetup::MODULE_ID, EntityClassInitialSetup::MOTHERBOARD_ID], true)
            ->entityTypeId(self::TRANSCEIVER_TYPE_ID)
            ->hasManufacturer()
            ->finish();
    }

    /**
     * Returns transceiver_type entity class definition.
     *
     * @return array
     */
    public static function transceiverTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::TRANSCEIVER_TYPE_ID, EntityClassInitialSetup::TRANSCEIVER_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns switch entity class definition.
     *
     * @return array
     */
    public static function switchDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::SWITCH_ID, EntityClassInitialSetup::SWITCH))
            ->parameters([
                'name' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 20),
                'description' =>
                    self::buildParam(true, EntityParameter::STRING),
                'serial_number' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 65)
            ])
            ->entityTypeId(self::SWITCH_TYPE_ID)
            ->hasManufacturer()
            ->hasLocation()
            ->finish();
    }

    /**
     * Returns switch_type entity class definition.
     *
     * @return array
     */
    public static function switchTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::SWITCH_TYPE_ID, EntityClassInitialSetup::SWITCH_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns fan entity class definition.
     *
     * @return array
     */
    public static function fanDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::FAN_ID, EntityClassInitialSetup::FAN))
            ->parameters([
                'description' =>
                    self::buildParam(true, EntityParameter::STRING),
                'serial_number' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 65)
            ])
            ->parentClassIds([EntityClassInitialSetup::SWITCH_ID])
            ->entityTypeId(self::FAN_TYPE_ID)
            ->finish();
    }

    /**
     * Returns fan_type entity class definition.
     *
     * @return array
     */
    public static function fanTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::FAN_TYPE_ID, EntityClassInitialSetup::FAN_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns module entity class definition.
     *
     * @return array
     */
    public static function moduleDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::MODULE_ID, EntityClassInitialSetup::MODULE))
            ->parameters([
                'description' =>
                    self::buildParam(true, EntityParameter::STRING),
                'serial_number' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 65)
            ])
            ->parentClassIds([EntityClassInitialSetup::SWITCH_ID])
            ->entityTypeId(self::MODULE_TYPE_ID)
            ->finish();
    }

    /**
     * Returns module_type entity class definition.
     *
     * @return array
     */
    public static function moduleTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::MODULE_TYPE_ID, EntityClassInitialSetup::MODULE_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns power_supply entity class definition.
     *
     * @return array
     */
    public static function powerSupplyDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::POWER_SUPPLY_ID, EntityClassInitialSetup::POWER_SUPPLY))
            ->parameters([
                'description' =>
                    self::buildParam(true, EntityParameter::STRING),
                'serial_number' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 65)
            ])
            ->parentClassIds([EntityClassInitialSetup::SWITCH_ID, EntityClassInitialSetup::SERVER_ID])
            ->entityTypeId(self::POWER_SUPPLY_TYPE_ID)
            ->finish();
    }

    /**
     * Returns power_supply_type entity class definition.
     *
     * @return array
     */
    public static function powerSupplyTypeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::POWER_SUPPLY_TYPE_ID, EntityClassInitialSetup::POWER_SUPPLY_TYPE))
            ->parameters([
                'type' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns wifi_ap entity class definition.
     *
     * @return array
     */
    public static function wifiApDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::WIFI_AP_ID, EntityClassInitialSetup::WIFI_AP))
            ->parameters([
                'name' =>
                    self::buildParam(true, EntityParameter::STRING, 100),
                'socket' =>
                    self::buildParam(false, EntityParameter::STRING),
                'serial_number' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 65),
                'mac_addr_eth' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 17),
                'mac_addr_wlan' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 17)
            ])
            ->entityTypeId(EntityClassInitialSetup::WIFI_PLATFORM_ID)
            ->hasLocation()
            ->finish();
    }

    /**
     * Returns wifi_ap_platform entity class definition.
     *
     * @return array
     */
    public static function wifiPlatformDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::WIFI_PLATFORM_ID, EntityClassInitialSetup::WIFI_PLATFORM))
            ->parameters([
                'name' =>
                    self::buildUniqueParam(true, EntityParameter::STRING)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns vlan entity class definition.
     *
     * @return array
     */
    public static function vLanDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::VLAN_ID, EntityClassInitialSetup::VLAN))
            ->parameters([
                'name' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 20),
                'description' =>
                    self::buildParam(false, EntityParameter::STRING, 100),
                'cidr_ipv4' =>
                    self::buildUniqueParam(false, EntityParameter::STRING, 15),
                'cidr_ipv6' =>
                    self::buildUniqueParam(false, EntityParameter::STRING, 45)
            ])
            ->finish();
    }

    /**
     * Returns wifi_account entity class definition.
     *
     * @return array
     */
    private static function wifiAccountDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::WIFI_ACCOUNT_ID, EntityClassInitialSetup::WIFI_ACCOUNT))
            ->parameters([
                'ssid' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 45),
                'login' =>
                    self::buildParam(false, EntityParameter::STRING, 20),
                'password' =>
                    self::buildParam(false, EntityParameter::STRING, 20),
                'max_connections' =>
                    self::buildParam(false, EntityParameter::INT)
            ])
            ->finish();
    }

    /**
     * Returns wifi_account_location entity class definition.
     *
     * @return array
     */
    private static function wifiAccountLocationDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::WIFI_ACCOUNT_LOCATIONS_ID, EntityClassInitialSetup::WIFI_ACCOUNT_LOCATIONS))
            ->parentClassIds([EntityClassInitialSetup::WIFI_ACCOUNT_ID])
            ->hasLocation()
            ->requireParent()
            ->finish();
    }

    /**
     * Returns server_user entity class definition.
     *
     * @return array
     */
    private static function serverUserDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::SERVER_USER_ID, EntityClassInitialSetup::SERVER_USER))
            ->parameters([
                'login' =>
                    self::buildUniqueParam(true, EntityParameter::STRING, 20)
            ])
            ->parentClassIds([self::SERVER_ID])
            ->requireParent()
            ->finish();
    }

    /**
     * Returns group_membership entity class definition.
     *
     * @return array
     */
    private static function groupMembershipDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::GROUP_MEMBERSHIP_ID, EntityClassInitialSetup::GROUP_MEMBERSHIP))
            ->parentClassIds([self::SERVER_USER_ID])
            ->entityTypeId(self::SERVER_GROUP_ID)
            ->requireParent()
            ->finish();
    }

    /**
     * Returns server_group entity class definition.
     *
     * @return array
     */
    private static function serverGroupDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::SERVER_GROUP_ID, EntityClassInitialSetup::SERVER_GROUP))
            ->parameters([
                'gid' => self::buildUniqueParam(true, EntityParameter::INT),
                'group' => self::buildUniqueParam(true, EntityParameter::STRING, 20)
            ])
            ->isType()
            ->finish();
    }

    /**
     * Returns web_page entity class definition.
     *
     * @return array
     */
    private static function webPageDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::WEB_PAGE_ID, EntityClassInitialSetup::WEB_PAGE))
            ->parameters([
                'url' => self::buildUniqueParam(true, EntityParameter::STRING, 255)
            ])
            ->parentClassIds([self::SERVER_ID, self::INSTITUTE_ID, self::EMPLOYEE_ID])
            ->finish();
    }

    /**
     * Returns institute entity class definition.
     *
     * @return array
     */
    private static function instituteDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::INSTITUTE_ID, EntityClassInitialSetup::INSTITUTE))
            ->parameters([
                'name' => self::buildUniqueParam(true, EntityParameter::STRING, 255)
            ])
            ->finish();
    }

    /**
     * Returns institute entity class definition.
     *
     * @return array
     */
    private static function employeeDefinition()
    {
        return (new EntityDefinitionBuilder(EntityClassInitialSetup::EMPLOYEE_ID, EntityClassInitialSetup::EMPLOYEE))
            ->parameters([
                'firstname' => self::buildParam(true, EntityParameter::STRING, 65),
                'lastname' => self::buildParam(true, EntityParameter::STRING, 65)
            ])
            ->parentClassIds([self::INSTITUTE_ID])
            ->requireParent()
            ->finish();
    }
}