
/*
 * Copyright 2011-2022 Cuberite Contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// this is apache2.0 since its taken from the old pluginmanager.

#pragma once

#include <functional>
#include <memory>
#include <list>

#include"StringUtils.h"
//#include "FunctionRef.h"

class cPlayer;
class cCommandOutputCallback;

class cCMDManager
{
public:

    /*
     *
     *   The following code is from Bindings/PluginManager, attempting to get command binding to work. I realized without uses, having the plugin system is kinda lame.
     *   New plan: Bake the commands in directly, aim for vanilla equality over adaptability!!! patches can be made to source if u want to mod it, its open source anyways ;-;
     *
     */

    enum CommandResult
    {
        crExecuted,
        crUnknownCommand,
        crError,
        //crBlocked, // plugins dont hook anymore.
        crNoPermission,
    };	

    /** Executes the specified in-game command.
    a_Split is the command string, split at the spaces.
    a_Player is the player executing the command, nullptr in case of the console.
    a_Command is the entire command string.
    a_Output is the sink into which the additional text returned by the command handler should be sent; only used for console commands. */
    /*using ExecuteCommand = cFunctionRef<bool(
        const AStringVector & a_Split,
        cPlayer * a_Player,
        const AString & a_Command,
        cCommandOutputCallback * a_Output //= nullptr
    )>;*/
    using ExecuteCommand = std::function<bool(
        const AStringVector & a_Split,
        cPlayer * a_Player,
        const AString & a_Command,
        cCommandOutputCallback * a_Output //= nullptr
    )>;

    using cCommandHandler = ExecuteCommand;

    class cCommandReg
    {
    public:
        /*cCommandReg(const AString& m_Permission, const AString& m_HelpString, cCommandHandlerPtr m_Handler)
            : m_Permission(m_Permission), m_HelpString(m_HelpString), m_Handler(std::move(m_Handler)) {}*/
        //cPlugin * m_Plugin;
        AString   m_Permission;  // Not used for console commands
        AString   m_HelpString;
        cCommandHandler m_Handler;
    } ;
        
    using CommandMap = std::map<AString, cCommandReg>;

    static const CommandMap m_Commands; // constant due to it being compiled in :)
	static const CommandMap m_ConsoleCommands;
	
    /** Tries to match a_Command to the internal table of commands, if a match is found, the corresponding class callback is called. Returns crExecuted if the command is executed. */
    CommandResult HandleCommand(cPlayer & a_Player, const AString & a_Command, bool a_ShouldCheckPermissions);
    /** Executes the command split into a_Split, as if it was given on the console.
	Returns true if executed. Output is sent to the a_Output callback */
	bool HandleConsoleCommand(const AStringVector & a_Split, cCommandOutputCallback & a_Output, const AString & a_Command);
};

