using System;
using System.Collections.Generic;

public class HiddenValueInt
{
    private int _offsetSeed;
    private int _newValue;

    public HiddenValueInt(int value)
    {
        Random newRandom = new Random(Environment.TickCount);
        _offsetSeed = newRandom.Next(int.MinValue, int.MaxValue);
        _newValue = value ^ _offsetSeed;
    }

    public void ReSeedValue()
    {
        int tempValue = Value;
        Random newRandom = new Random(Environment.TickCount);
        _offsetSeed = newRandom.Next(int.MinValue, int.MaxValue);
        _newValue = tempValue ^ _offsetSeed;
    }

    public int Value
    {
        get
        {
            return _offsetSeed ^ _newValue;
        }
        set
        {
            _newValue = value ^ _offsetSeed;
        }
    }
    
    public override bool Equals(object obj)
    {
        return Equals(obj as HiddenValueInt);
    }

    public bool Equals(HiddenValueInt rhs)
    {
        if (rhs is null)
        {
            return false;
        }

        if (ReferenceEquals(this, rhs))
        {
            return true;
        }

        if (GetType() != rhs.GetType())
        {
            return false;
        }
                
        return Equals(rhs.Value);
    }

    public bool Equals(int rhs)
    {
        bool result = false;
        if (Value == rhs)
        {
            result = true;
        }
        return result;
    }

    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }

    public static explicit operator int(HiddenValueInt rhs)
    {
        return rhs.Value;
    }

    public static bool operator ==(HiddenValueInt lhs, HiddenValueInt rhs)
    {
        if (lhs is null)
        {
            if (rhs is null)
            {
                return true;
            }

            return false;
        }

        return lhs.Equals(rhs);
    }

    public static bool operator !=(HiddenValueInt lhs, HiddenValueInt rhs)
    {
        return !(lhs == rhs);
    }

    public static bool operator ==(HiddenValueInt lhs, int rhs)
    {
        if (lhs is null)
        {
            return false;
        }

        return lhs.Equals(rhs);
    }

    public static bool operator !=(HiddenValueInt lhs, int rhs)
    {
        return !(lhs.Value == rhs);
    }

    public static bool operator ==(int lhs, HiddenValueInt rhs)
    {
        if (rhs is null)
        {
            return false;
        }

        return rhs.Equals(lhs);
    }

    public static bool operator !=(int lhs, HiddenValueInt rhs)
    {
        return !(lhs == rhs.Value);
    }

    public static HiddenValueInt operator +(HiddenValueInt a, HiddenValueInt b)
    {
        int tempInt = a.Value + b.Value;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator +(HiddenValueInt a, int b)
    {
        int tempInt = a.Value + b;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator +(int a, HiddenValueInt b)
    {
        int tempInt = a + b.Value;        
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator -(HiddenValueInt a, HiddenValueInt b)
    {
        int tempInt = a.Value - b.Value;        
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator -(HiddenValueInt a, int b)
    {
        int tempInt = a.Value - b;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator -(int a, HiddenValueInt b)
    {
        int tempInt = a - b.Value;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator *(HiddenValueInt a, HiddenValueInt b)
    {
        int tempInt = a.Value * b.Value;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator *(HiddenValueInt a, int b)
    {
        int tempInt = a.Value * b;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator *(int a, HiddenValueInt b)
    {
        int tempInt = a * b.Value;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator /(HiddenValueInt a, HiddenValueInt b)
    {
        int tempInt = a.Value / b.Value;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator /(HiddenValueInt a, int b)
    {
        int tempInt = a.Value / b;
        return new HiddenValueInt(tempInt);
    }

    public static HiddenValueInt operator /(int a, HiddenValueInt b)
    {
        int tempInt = a / b.Value;
        return new HiddenValueInt(tempInt);
    }
}

