// SPDX-License-Identifier: GPL-2.0-or-later
/*
    Authors:
      bulia byak <buliabyak@gmail.com>

    Copyright (C) 2004 Authors

    Released under GNU GPL v2+, read the file 'COPYING' for more information.
*/
#ifndef SEEN_COLOR_RGBA_H
#define SEEN_COLOR_RGBA_H

#include <cassert>
#include <cmath>

/**
 * A class to contain a floating point RGBA color as one unit.
 */
class ColorRGBA {
public:

    /**
     * A constructor to create the color from four floating point values.
     * Load the values into the array of floats in this object.
     *
     * @param  c0  Red
     * @param  c1  Green
     * @param  c2  Blue
     * @param  c3  Alpha
     */
    ColorRGBA(float c0, float c1, float c2, float c3)
    {
        _c[0] = c0; _c[1] = c1;
        _c[2] = c2; _c[3] = c3;
    }

    /**
     * Create a quick ColorRGBA with all zeros.
     */
    ColorRGBA() : _c{0.0,0.0,0.0,0.0}
    {
    }

    /**
     * A constructor to create the color from an unsigned int, as found everywhere when dealing with colors.
     *
     * Separate the values and load them into the array of floats in this object.
     * @param  intcolor   rgba32 "unsigned int representation (0xRRGGBBAA)
     */
    ColorRGBA(unsigned int intcolor)
    {
         _c[0] = ((intcolor & 0xff000000) >> 24) / 255.0;
         _c[1] = ((intcolor & 0x00ff0000) >> 16) / 255.0;
         _c[2] = ((intcolor & 0x0000ff00) >>  8) / 255.0;
         _c[3] = ((intcolor & 0x000000ff) >>  0) / 255.0;

    }

    /**
     * Create a ColorRGBA using an array of floats.
     *
     * Go through each entry in the array and put it into \c _c.
     *
     * @param  in_array  The values to be placed into the object
     */
    ColorRGBA(float in_array[4])
    {
        for (int i = 0; i < 4; i++)
            _c[i] = in_array[i];
    }

    /**
     * Overwrite the values in this object with another \c ColorRGBA.
     * Copy all the values from \c m into \c this.
     *
     * @param  m  Values to use for the array.
     * @return This ColorRGBA object.
     */
    ColorRGBA &operator=(ColorRGBA const &m) {
        for (unsigned i = 0 ; i < 4 ; ++i) {
            _c[i] = m._c[i];
        }
        return *this;
    }

    /**
     * Grab a particular value from the ColorRGBA object.
     * First checks to make sure that the value is within the array,
     * and then return the value if it is.
     *
     * @param  i  Which value to grab.
     * @return The requested value.
     */
    float operator[](unsigned int const i) const {
        assert( unsigned(i) < 4 );
        return _c[i];
    }

    /**
     * Check to ensure that two \c ColorRGBA's are equal.
     * Check each value to see if they are equal.  If they all are,
     * return true.
     *
     * @param  other  The guy to check against.
     * @return Whether or not they are equal.
     */
    bool operator== (const ColorRGBA &other) const {
        for (int i = 0; i < 4; i++) {
            if (_c[i] != other[i])
                return false;
        }
        return true;
    }

    bool operator!=(ColorRGBA const &o) const {
        return !(*this == o);
    }

    /**
     * Average two \c ColorRGBAs to create another one.
     * This function goes through all the points in the two objects and
     * merges them together based on the weighting.  The current objects
     * value are multiplied by 1.0 - weight and the second object by weight.
     * This means that they should always be balanced by the parameter.
     *
     * @param  second  The second RGBA, with this being the first
     * @param  weight  How much of each should be used.  Zero is all
     * this while one is all the second.  Default is
     * half and half.
     */
    ColorRGBA average (const ColorRGBA &second, const float weight = 0.5) const {
        float returnval[4];

        for (int i = 0; i < 4; i++) {
            returnval[i] = _c[i] * (1.0 - weight) + second[i] * weight; 
        }

        return ColorRGBA(returnval[0], returnval[1], returnval[2], returnval[3]);
    }

    /**
     * Give the rgba32 "unsigned int" representation of the color.
     * round each components*255 and combine them (RRGGBBAA).
     * WARNING : this reduces color precision (from float to 0->255 int per component)
     * but it should be expected since we request this kind of output
     */
    unsigned int getIntValue() const {

        return
            (int(round(_c[0]*255)) << 24) | 
            (int(round(_c[1]*255)) << 16) | 
            (int(round(_c[2]*255)) <<  8) | 
            (int(round(_c[3]*255)));
    }

private:
    /** Array of values that are stored. */
    float _c[4];
};


#endif // SEEN_COLOR_RGBA_H

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
