/*
    Copyright (c) 2026 Christian Schoenebeck

    This file is part of "gigedit" and released under the terms of the
    GNU General Public License version 2.
*/

#ifndef GIGEDIT_DIMREG_DIFF_H
#define GIGEDIT_DIMREG_DIFF_H

#include <map>
#include <string>
#include "global.h"

/** @brief Identify differences between a number of DimensionRegion objects.
 *
 * This is used for colored highlighting of respective parameters where there
 * are multiple values for the current expanded selection.
 *
 * This is just the logical class that peforms the difference checking. It works
 * by calling compare() for the individual members of a large number of
 * DimensionRegion objects and comparing them with the primary selection's
 * DimensionRegion object. If a difference is detected, a boolean flag is set
 * for the respective DimensionRegion member variable.
 *
 * After comparison is completed, hasDiff() can be called to check whether the
 * respective DimensionRegion member variable has multiple values, i.e. to
 * update the respective UI parameter control accordingly,
 */
class DimRegDiff {
public:
    DimRegDiff(gig::DimensionRegion* primarySelection) {
        primaryDR = primarySelection;
    }

    template<typename T>
    void compare(const gig::DimensionRegion* dr, const T& member) {
        std::ptrdiff_t offset = ((char*)(void*)&member) - ((char*)(void*)dr);
        const T* memberMain = (const T*) (((char*)(void*)primaryDR) + offset);
        members[offset] |= (*memberMain != member);
    }

    template<typename T>
    void compareSymbolic(std::string name, const T& valueA, const T& valueB) {
        symbolic[name] |= (valueA != valueB);
    }

    template<typename T>
    bool hasDiff(const T& member) {
        std::ptrdiff_t offset = ((char*)(void*)&member) - ((char*)(void*)primaryDR);
        return members[offset];
    }

    bool hasDiffSymbolic(std::string name) {
        return symbolic[name];
    }
private:
    gig::DimensionRegion* primaryDR;
    std::map<std::ptrdiff_t,bool> members;
    std::map<std::string,bool> symbolic;
};

#endif // GIGEDIT_DIMREG_DIFF_H
