/*
 * File: obj-properties.c
 * Purpose: Functions to deal with object properties
 *
 * Copyright (c) 2014 Chris Carr, Nick McConnell
 * Copyright (c) 2019 MAngband and PWMAngband Developers
 *
 * This work is free software; you can redistribute it and/or modify it
 * under the terms of either:
 *
 * a) the GNU General Public License as published by the Free Software
 *    Foundation, version 2, or
 *
 * b) the "Angband licence":
 *    This software may be copied and distributed for educational, research,
 *    and not for profit purposes provided that this copyright and statement
 *    are included in all such copies.  Other copyrights may also apply.
 */


#include "s-angband.h"


struct obj_property *obj_properties;


struct obj_property *lookup_obj_property(int type, int index)
{
    struct obj_property *prop;
    int i;

    /* Find the right property */
    for (i = 0; i < z_info->property_max; i++)
    {
        prop = &obj_properties[i];
        if ((prop->type == type) && (prop->index == index))
            return prop;

        /* Special case - stats count as mods */
        if ((type == OBJ_PROPERTY_MOD) && (prop->type == OBJ_PROPERTY_STAT) &&
            (prop->index == index))
        {
            return prop;
        }
    }

    return NULL;
}


/*
 * Create a "mask" of object flags of a specific type or ID threshold.
 *
 * f is the flag array we're filling
 * id is whether we're masking by ID level
 * ... is the list of flags or ID types we're looking for
 *
 * N.B. OFT_MAX must be the last item in the ... list
 */
void create_obj_flag_mask(bitflag *f, bool id, ...)
{
    int i, j;
    va_list args;

    of_wipe(f);

    va_start(args, id);

    /* Process each type in the va_args */
    for (i = va_arg(args, int); i != OFT_MAX; i = va_arg(args, int))
    {
        for (j = 0; j < z_info->property_max; j++)
        {
            struct obj_property *prop = &obj_properties[j];

            if (prop->type != OBJ_PROPERTY_FLAG) continue;
            if ((id && prop->id_type == i) || (!id && prop->subtype == i))
                of_on(f, prop->index);
        }
    }

    va_end(args);
}


/*
 * Print a message when an object flag is identified by use.
 *
 * flag is the flag being noticed
 * name is the object name
 */
void flag_message(struct player *p, int flag, char *name)
{
    struct obj_property *prop = lookup_obj_property(OBJ_PROPERTY_FLAG, flag);
    char buf[MSG_LEN] = "\0";
    const char *next;
    const char *s;
    const char *tag;
    const char *in_cursor;
    size_t end = 0;

    /* See if we have a message */
    if (!prop->msg) return;
    in_cursor = prop->msg;

    next = strchr(in_cursor, '{');
    while (next)
    {
        /* Copy the text leading up to this { */
        strnfcat(buf, MSG_LEN, &end, "%.*s", next - in_cursor, in_cursor);

        s = next + 1;
        while (*s && isalpha((unsigned char)*s)) s++;

        /* Valid tag */
        if (*s == '}')
        {
            /* Start the tag after the { */
            tag = next + 1;
            in_cursor = s + 1;

            if (strncmp(tag, "name", 4) == 0)
                strnfcat(buf, MSG_LEN, &end, "%s", name);
        }

        /* An invalid tag, skip it */
        else
            in_cursor = next + 1;

        next = strchr(in_cursor, '{');
    }
    strnfcat(buf, MSG_LEN, &end, in_cursor);

    msg(p, buf);
}


/*
 * Return the sustain flag of a given stat.
 */
int sustain_flag(int stat)
{
    if ((stat < 0) || (stat >= STAT_MAX)) return -1;

    return stat + 1;
}
