// The MIT License (MIT)
//
// Copyright (C) 2026 Scott Duensing
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

// frmParser.h -- callback-based .frm text parser
//
// Shared by the form runtime (formrt.c) and the visual designer
// (ideDesigner.c). The parser walks the .frm text, recognises
// "Begin Form", "Begin Menu", "Begin <Control>", "End", and
// "Key = Value" lines, and calls back into the caller for each
// semantic event. The caller owns all data structures -- the
// parser keeps only internal block-nesting state.

#ifndef DVXBASIC_FRMPARSER_H
#define DVXBASIC_FRMPARSER_H

#include <stdbool.h>
#include <stdint.h>

// Parser limits.  Consumers size their own line/name buffers and
// nesting stacks from these so the two sides can never disagree.
#define FRM_MAX_LINE_LEN      512   // longest "Key = Value" line, including the value
#define FRM_MAX_TOKEN_LEN     64    // longest Begin-line token or property key
#define FRM_MAX_NESTING       16    // deepest Begin/End block nesting

// Callbacks supplied by the consumer. Any field may be NULL.
typedef struct FrmParserCbsT {
    void *userData;

    // "Begin Form <name>".  Return false to abort parsing.
    bool (*onFormBegin)(void *userData, const char *name);

    // Form-level "Key = Value" property (not inside any control or menu).
    void (*onFormProp)(void *userData, const char *key, const char *value);

    // "Begin Menu <name>" at the given nesting level (0 = top-level).
    void (*onMenuBegin)(void *userData, const char *name, int32_t level);

    // "End" for a menu item.
    void (*onMenuEnd)(void *userData);

    // Menu-item "Key = Value" property.
    void (*onMenuProp)(void *userData, const char *key, const char *value);

    // "Begin <Type> <Name>" for a non-Form, non-Menu control.
    void (*onCtrlBegin)(void *userData, const char *typeName, const char *name);

    // "End" for a control block.
    void (*onCtrlEnd)(void *userData);

    // Control-level "Key = Value" property.
    void (*onCtrlProp)(void *userData, const char *key, const char *value);

    // Outer Form's "End" was reached.  trailingSrc points into the
    // input buffer just past the End, with trailingLen bytes remaining.
    // The designer uses this to capture the BASIC code section.
    void (*onFormEnd)(void *userData, const char *trailingSrc, int32_t trailingLen);
} FrmParserCbsT;

// Parse a .frm text.  Returns true on success, false if the VERSION
// line rejects the input or onFormBegin returns false.
bool frmParse(const char *source, int32_t sourceLen, const FrmParserCbsT *cb);

// Parse a trimmed "Key = Value" line into key and value buffers.
// value has trailing whitespace stripped but quotes are preserved.
void frmParseKeyValue(const char *line, char *key, int32_t keyMax, char *value, int32_t valueMax);

// Strip surrounding double quotes from val, in place.  No-op if the
// string is not quoted.
void frmStripQuotes(char *val);

// Classify a value string as a BASIC boolean.  True / -1 -> true;
// anything else -> false.
bool frmParseBool(const char *val);

// Classify a value string as a BASIC boolean with an explicit default:
// True / -1 -> true, False / 0 -> false, anything else -> defaultValue.
// Use for properties whose unset state is true (menu Enabled/Visible).
bool frmParseBoolDefault(const char *val, bool defaultValue);

#endif // DVXBASIC_FRMPARSER_H
