<?php

namespace objects;

use classes\db;
use classes\object_property;
use Exception;
use traits\db_object_t;

class groups_permissions_o extends db
{
    use db_object_t;

    public object_property $group_id;
    public object_property $permission;

    public function structure(): void
    {
        $this->setTable('groups_permissions');
    }

    /**
     * Add a permission to a group
     * @param int $group_id
     * @param string $permission
     * @return void
     * @throws Exception If the object was not created successfully
     */
    public function add(int $group_id, string $permission): void
    {
        // Check if the group exists
        $group = new groups_o();
        $group->select($group_id);
        $group->requireSelected();
        // Check if the permission already exists for the group
        $isAlreadyDefined = self::getFieldsWhere([
            'group_id' => $group_id,
            'permission' => $permission
        ], ['id']);
        // Throw an exception if the permission already exists for the group
        if ($isAlreadyDefined) {
            throw new Exception('The permission already exists for the group.');
        }
        // Add the permission
        $tmp_id = self::add_object([
            'group_id' => $group_id,
            'permission' => $permission
        ]);
        $this->id = $tmp_id;
        self::getObjectProperties();
        self::objectChanged();
        if (!$this->id) {
            throw new Exception('The permission was not created successfully.');
        }
    }

    public function getObjectProperties(): void
    {
        $this->group_id = new object_property($this->table, $this->id, 'group_id', 'int', false);
        $this->permission = new object_property($this->table, $this->id, 'permission', 'string', false);
    }

    public function objectChanged(): void
    {
        //TODO: Add cache invalidation
    }

    /**
     * Remove a permission from a group
     * @param int $group_id
     * @param string $permission
     * @return void
     * @throws Exception If the permission does not exist for the group
     * @throws Exception If the object was not deleted successfully
     * @throws Exception If the group does not exist
     */
    public function remove(int $group_id, string $permission): void
    {
        // Check if the group exists
        $group = new groups_o();
        $group->select($group_id);
        $group->requireSelected();
        // Check if the permission exists for the group
        $isDefined = self::getFieldsWhere([
            'group_id' => $group_id,
            'permission' => $permission
        ], ['id']);
        // Throw an exception if the permission does not exist for the group
        if (!$isDefined) {
            throw new Exception('The permission does not exist for the group.');
        }
        // Get the id of the permission entry in the database
        $id = $isDefined[0]['id'];
        // Remove the permission
        $tmp_id = new groups_permissions_o();
        $tmp_id->select((int)$id);
        $tmp_id->requireSelected();
        $tmp_id->delete();
    }

    public function asArray(): array
    {
        return [
            'id' => (int)$this->id,
            'group_id' => (int)$this->group_id->value(),
            'permission' => (string)$this->permission->value()
        ];
    }

    /**
     * Get all permissions for a group
     * @param int $group_id
     * @return array
     */
    public function getGroupPermissions(int $group_id): array
    {
        $raw_permissions = self::getFieldsWhere([
            'group_id' => $group_id
        ], ['permission']);
        $permissions = [];
        foreach ( $raw_permissions as $permission ) {
            $permissions[] = $permission['permission'];
        }
        return $permissions;
    }

    /**
     * Get all permissions for a group matching a regex
     * @throws Exception If the group does not exist
     */
    public function getGroupPermissionsMatching(int $id, string $regex): array
    {
        // Check if the group exists
        $group = new groups_o();
        $group->select($id);
        if (!$group->exists()) {
            return [];
        }
        // Get the permissions
        $permissions = self::getFieldsWhere([
            'group_id' => $id
        ], ['permission']);
        // Filter the permissions
        return array_filter($permissions, function ($permission) use ($regex) {
            return preg_match($regex, $permission['permission']);
        });
    }
}