using System;

namespace VMdemo.Core
{
    [Serializable]
    public class SimulationConfig
    {
        public int vaBits = 32;
        public int pageSizeKB = 4;
        public int physicalMemoryMB = 64;
        public int tlbEntries = 16;
        public int accessCount = 100;
        public int pageFaultPenalty = 100;

        public ulong PageSizeBytes => pageSizeKB > 0 ? (ulong)pageSizeKB * 1024UL : 0UL;

        public ulong PhysicalMemoryBytes => physicalMemoryMB > 0 ? (ulong)physicalMemoryMB * 1024UL * 1024UL : 0UL;

        public int OffsetBits
        {
            get
            {
                return TryGetLog2(PageSizeBytes, out var bits) ? bits : -1;
            }
        }

        public int VpnBits
        {
            get
            {
                var offsetBits = OffsetBits;
                return offsetBits >= 0 ? vaBits - offsetBits : -1;
            }
        }

        public ulong FrameCount
        {
            get
            {
                var pageSizeBytes = PageSizeBytes;
                if (pageSizeBytes == 0UL)
                {
                    return 0UL;
                }

                return PhysicalMemoryBytes / pageSizeBytes;
            }
        }

        private static bool TryGetLog2(ulong value, out int bits)
        {
            bits = -1;
            if (value == 0UL || (value & (value - 1UL)) != 0UL)
            {
                return false;
            }

            bits = 0;
            while (value > 1UL)
            {
                value >>= 1;
                bits++;
            }

            return true;
        }
    }
}
