#pragma once
#include "inc.h"
#include <panda/string.h>
#include <panda/iterator.h>

namespace panda { namespace protocol { namespace websocket {

using panda::string;
using panda::IteratorPair;

struct FrameHeader {
    Opcode   opcode;
    bool     fin;
    bool     rsv1;
    bool     rsv2;
    bool     rsv3;
    bool     has_mask;
    uint32_t mask;
    uint64_t length;

    FrameHeader () : mask(0), length(0), _state(State::FIRST), _len16(0) {}

    FrameHeader (Opcode opcode, bool final, bool rsv1, bool rsv2, bool rsv3, bool has_mask, uint32_t mask) :
        opcode(opcode), fin(final), rsv1(rsv1), rsv2(rsv2), rsv3(rsv3), has_mask(has_mask), mask(mask) {}

    bool is_control () const { return is_control_opcode(opcode); }

    bool   parse   (string& buf);
    string compile (size_t plen) const; // returns string with enough space to fit <plen> bytes after header

    void reset () {
        mask   = 0;
        length = 0;
        _state = State::FIRST;
        _len16 = 0;
    }

    static bool   parse_close_payload   (const string& payload, uint16_t& code, string& message);
    static string compile_close_payload (uint16_t code, string_view message);

    static bool is_control_opcode (Opcode opcode) { return opcode >= Opcode::CLOSE; }


private:
    enum class State { FIRST, SECOND, LENGTH, MASK, DONE };
    State    _state;
    uint8_t  _slen;
    uint16_t _len16;
};

}}}
