<?php
/**
 * app/classes/permissions.php
 *
 * This class handles all the hard-coded permissions.
 *
 * @version 3.0
 * @author  Joey Kimsey <Joey@thetempusproject.com>
 * @link    https://TheTempusProject.com
 * @license https://opensource.org/licenses/MIT [MIT LICENSE]
 */
namespace TheTempusProject\Classes;

use TheTempusProject\Canary\Bin\Canary as Debug;
use TheTempusProject\Bedrock\Functions\Check;
use TheTempusProject\Houdini\Classes\Forms;
use TheTempusProject\Bedrock\Functions\Input;
use TheTempusProject\Houdini\Classes\Template;

class Permissions {
    public static $permissions = false;
    private static $location = false;
    private static $initialized = false;

    /**
     * Default constructor which will attempt to load the permissions from the location specified.
     *
     * @param {string} [$location]
     * @return {null|object}
     */
    public function __construct( $location = '' ) {
        if ( self::$initialized !== false ) {
            Debug::log( 'Permissions already initialized.' );
            return $this;
        }
        if ( empty( $location ) ) {
            $location = PERMISSIONS_JSON;
        }
        self::$initialized = $this->load( $location );
        if ( self::$initialized !== false ) {
            Debug::log( 'Permissions initialization succeeded.' );
            return $this;
        }
        Debug::warn( 'Permissions initialization failed.' );
    }

    /**
     * Attempts to retrieve then set the configuration from a file.
     * @note This function will reset the permissions every time it is used.
     *
     * @param {string} [$location]
     * @return {bool}
     */
    public function load( $location ) {
        self::$permissions = $this->getPermsFile( $location );
        self::$location = $location;
        if ( self::$permissions === false || empty( self::$permissions ) ) {
            Debug::warn( 'Permissions load failed.' );
            return false;
        }
        Debug::log( 'Permissions load succeeded.' );
        return true;
    }

    /**
     * Opens and decodes the permissions json from the location provided.
     *
     * @param {string} [$location]
     * @return {bool|array}
     */
    public function getPermsFile( $location ) {
        if ( file_exists( $location ) ) {
            Debug::debug( "Permissions json found: $location" );
            return json_decode( file_get_contents( $location ), true );
        } else {
            Debug::warn( "Permissions json not found: $location" );
            return false;
        }
    }

    /**
     * Retrieves the permissions option for $name.
     *
     * @param {string} [$name]
     * @return {WILD}
     */
    public function get( $name ) {
        if ( self::$permissions === false ) {
            Debug::warn( 'Permissions not loaded.' );
            return;
        }
        if ( isset( self::$permissions[$name] ) ) {
            return self::$permissions[$name];
        }
        Debug::warn( "Permission not found: $name" );
        return;
    }

    /**
     * Saves the current permissions.
     *
     * @param {bool} [$default] - Whether or not to save a default copy.
     * @return {bool}
     */
    public function save( $save_backup = true ) {
        if ( self::$permissions === false ) {
            Debug::warn( 'Permissions not loaded.' );
            return false;
        }
        if ( self::$location === false ) {
            Debug::warn( 'Permissions location not set.' );
            return false;
        }
        if ( $save_backup ) {
            $locationArray = explode( '.', self::$location );
            $locationArray[] = 'bak';
            $backupLoction = implode( '.', $locationArray );
            if ( !file_put_contents( $backupLoction, json_encode( self::$permissions ) ) ) {
                return false;
            }
        }

        if ( file_put_contents( self::$location, json_encode( self::$permissions ) ) ) {
            return true;
        }
        return false;
    }

    /**
     * Adds a new permission to the $permissions array.
     *
     * @param {string} [$name]
     * @param {string} [$value]
     * @return {bool}
     */
    public function add( $permName, $details ) {
        if ( !Check::simpleName( $permName ) ) {
            Debug::error( "Permission name invalid: $permName" );
            return false;
        }
        if ( isset( self::$permissions[$permName] ) ) {
            Debug::warn( "Permission already exists: $permName" );
            return false;
        }
        if ( self::$permissions === false ) {
            self::$permissions = [];
        }
        self::$permissions[$permName] = $details;
        return true;
    }

    /**
     * Adds many new permissions to the $permissions array.
     *
     * @param {array} [$data]
     * @return {bool}
     */
    public function addMany( $data ) {
        if ( !is_array( $data ) ) {
            Debug::error( 'Permissions must be an array.' );
            return false;
        }
        foreach ( $data as $name => $value ) {
            $this->add( $name, $value );
        }
        return true;
    }

    /**
     * Removes an existing permission from the $permissions array.
     *
     * @param {string} [$name]
     * @param {string} [$save]
     * @return {bool}
     */
    public function remove( $name, $save = false ) {
        if ( self::$permissions === false ) {
            Debug::warn( 'Permissions not loaded.' );
            return false;
        }
        if ( !isset( self::$permissions[$name] ) ) {
            Debug::error( "Permission does not exist: $name" );
            return false;
        }
        unset( self::$permissions[$name] );
        if ( $save === true ) {
            return $this->save();
        }
        return true;
    }

    public function getDefaultPermissionsArray() {
        if ( self::$permissions === false ) {
            Debug::warn( 'Permissions not loaded.' );
            return false;
        }
        $permsArray = [];
        foreach ( self::$permissions as $name => $details ) {
            $permsArray[$name] = $details['default'];
        }
        return $permsArray;
    }

    public function convertFormToArray() {
        $permsArray = [];
        foreach ( self::$permissions as $name => $details ) {
            if ( Input::exists( $name ) ) {
                $permsArray[$name] = true;
            } else {
                $permsArray[$name] = false;
            }
        }
        return $permsArray;
    }

    public function getDefault( $name ) {
        $perm = $this->get( $name );
        if ( empty( $perm ) || empty( $perm['default'] ) ) {
            Debug::warn( "Permission Default not found: $name" );
            return;
        }
    }

    public function getPrettyName( $name ) {
        $pref = $this->get( $name );
        if ( empty( $pref ) || empty( $pref['pretty'] ) ) {
            Debug::warn( "Permission Pretty Name not found: $name" );
            return;
        }
        return $pref['pretty'];
    }

    public function getFormHtml( $populated = [] ) {
        $form = '';
        foreach ( self::$permissions as $name => $details ) {
            if ( isset( $populated[$name] ) && $populated[$name] !== false ) {
                $checked = true;
            } else {
                $checked = false;
            }
            $form .= self::getFieldEditHtml( $name, $checked, $details['pretty'] );
        }
        return $form;
    }
    
    public static function getFieldEditHtml( $name, $default, $pretty ) {
        $fieldname = str_ireplace( '/', '-', $name );
        $fieldHtml = Forms::getSwitchHtml( $fieldname, [ 'true', 'false' ], $default );
        $html = '';
        $html .= '<div class="mb-3 row">';
        $html .= '<label for="' . $fieldname . '" class="col-lg-6 col-form-label text-end">' . $pretty . '</label>';
        $html .= '<div class="col-lg-6">';
        $html .= $fieldHtml;
        $html .= '</div>';
        $html .= '</div>';
        return Template::parse( $html );
    }
}
