/**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.

* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

#pragma once
#include "engine/cmd_interface.h"

class CmdReceiver;

// RawMsgStatus.
custom_enum(RawMsgStatus, PROCESSED = 0, EXCEED_TICK, FAILED);

typedef function<CmdInput (const Unit&, char hotkey, const PointF& p, const UnitId &target_id, const GameEnv &)> EventResp;

class RawToCmd {
private:
    // Internal status.
    PlayerId _player_id;
    set<UnitId> _sel_unit_ids;
    char _last_key;

    map<char, EventResp> _hotkey_maps;

    void select_new_units(const set<UnitId>& ids) {
        _sel_unit_ids = ids;
        _last_key = '~';
    }

    void clear_state() {
        _last_key = '~';
        _sel_unit_ids.clear();
    }

    void add_hotkey(const string &keys, EventResp func);
    void setup_hotkeys();

    static bool is_mouse_motion(char c) { return c == 'L' || c == 'R' || c == 'B'; }

public:
    RawToCmd(PlayerId player_id = INVALID) : _player_id(player_id), _last_key('~') { setup_hotkeys(); }
    RawMsgStatus Process(Tick tick, const GameEnv &env, const string&s, vector<CmdBPtr> *cmds, vector<UICmd> *ui_cmds);

    void SetId(PlayerId id) {
        _player_id = id;
        clear_state();
    }
    PlayerId GetPlayerId() const { return _player_id; }

    bool IsUnitSelected() const { return ! _sel_unit_ids.empty(); }
    bool IsSingleUnitSelected() const { return _sel_unit_ids.size() == 1; }
    bool IsUnitSelected(const UnitId& id) const { return _sel_unit_ids.find(id) != _sel_unit_ids.end(); }
    void ClearUnitSelection() { _sel_unit_ids.clear(); }
    const set<UnitId> &GetAllSelectedUnits() const { return _sel_unit_ids; }

    void NotifyDeleted(const UnitId& id) {
        auto it = _sel_unit_ids.find(id);
        if (it != _sel_unit_ids.end()) {
            _sel_unit_ids.erase(it);
        }
    }
};

