module yamalib.util.systeminfo;

private import std.stdio;
private import std.string;

// windows
private import std.c.windows.windows;

version(Win32){

//-- OS情報
struct OSVERSIONINFOW {
    uint   dwOSVersionInfoSize;
    uint   dwMajorVersion;
    uint   dwMinorVersion;
    uint   dwBuildNumber;
    uint   dwPlatformId;
    char   szCSDVersion[ 128 ];     // Maintenance string for PSS usage
    ushort wServicePackMajor;
    ushort wServicePackMinor;
    ushort wSuiteMask;
    ubyte  wProductType;
    ubyte  wReserved;
};

enum {
	VER_NT_WORKSTATION            =  0x0000001,
	VER_NT_DOMAIN_CONTROLLER      =  0x0000002,
	VER_NT_SERVER                 =  0x0000003,
}

enum {
	VER_SERVER_NT                      =  0x80000000,
	VER_WORKSTATION_NT                 =  0x40000000,
	VER_SUITE_SMALLBUSINESS            =  0x00000001,
	VER_SUITE_ENTERPRISE               =  0x00000002,
	VER_SUITE_BACKOFFICE               =  0x00000004,
	VER_SUITE_COMMUNICATIONS           =  0x00000008,
	VER_SUITE_TERMINAL                 =  0x00000010,
	VER_SUITE_SMALLBUSINESS_RESTRICTED =  0x00000020,
	VER_SUITE_EMBEDDEDNT               =  0x00000040,
	VER_SUITE_DATACENTER               =  0x00000080,
	VER_SUITE_SINGLEUSERTS             =  0x00000100,
	VER_SUITE_PERSONAL                 =  0x00000200,
	VER_SUITE_BLADE                    =  0x00000400,
	VER_SUITE_EMBEDDED_RESTRICTED      =  0x00000800,
}

enum {
	VER_PLATFORM_WIN32s         =    0,
	VER_PLATFORM_WIN32_WINDOWS  =    1,
	VER_PLATFORM_WIN32_NT       =    2,
}

extern(Windows) export bool GetVersionExA(
    OSVERSIONINFOW* lpVersionInformation
    );
    
alias GetVersionExA GetVersionEx;

// ビデオカード
struct DISPLAY_DEVICE {
    uint  cb;
    char   DeviceName[32];
    char   DeviceString[128];
    uint  StateFlags;
    char   DeviceID[128];
    char   DeviceKey[128];
}

extern(Windows) export bool EnumDisplayDevices(void*, uint, DISPLAY_DEVICE*, uint);
	
	
//-- メモリ
struct MEMORYSTATUS {
    uint dwLength;
    uint dwMemoryLoad;
    uint dwTotalPhys;
    uint dwAvailPhys;
    uint dwTotalPageFile;
    uint dwAvailPageFile;
    uint dwTotalVirtual;
    uint dwAvailVirtual;
};

extern(Windows) export void GlobalMemoryStatus(
	 MEMORYSTATUS*	  lpBuffer
	 );

} else {
	// Win32以外
	
}



class SystemInfo {
	
	
	/// メモリー状況を更新します
	static void updateMemoryInfo() {
		GlobalMemoryStatus (&stat);
	}
	
	/// マシンの物理メモリサイズを取得する
	static uint getPhysMemory() {
version(Win32){
		return stat.dwTotalPhys;
} else {
		return 0UL;
}
	}
	
	/// 空きメモリサイズの取得
	static uint getAvailPhysMemory() {
version(Win32){
		return stat.dwAvailPhys;
} else {
		return 0UL;
}
	}
	/// ページングファイルのバイト数
	static uint getTotalPageFile() {
version(Win32){
		return stat.dwTotalPageFile;
} else {
		return 0UL;
}
	}
	
	/// ページングファイルの空きバイト数
	static uint getAvailPageFile() {
version(Win32){
		return stat.dwAvailPageFile;
} else {
		return 0UL;
}
	}
	
	/// 仮想メモリのバイト数
	static uint getTotalVirtual() {
version(Win32){
		return stat.dwTotalVirtual;
} else {
		return 0UL;
}
	}
	
	/// 仮想メモリの空きバイト数	
	static uint getAvailVirtual() {
version(Win32){
		return stat.dwAvailVirtual;
} else {
		return 0UL;
}
	}
	
	
	/// ＯＳ名を取得する
	static char[] getOSName() {
version(Win32){
		char[256] osname;
		OSVERSIONINFOW ovi;
		ovi.dwOSVersionInfoSize = OSVERSIONINFOW.sizeof;
		GetVersionEx( &ovi );

        //Windows95/98系
        if(ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
            //Windows 95
            if(ovi.dwMinorVersion == 0) {
                if(ovi.wServicePackMajor == 0) {
                    sprintf(.toStringz(osname), .toStringz("Microsoft Windows 95"));
                } else {
                    sprintf(.toStringz(osname), .toStringz("Microsoft Windows 95 with Servise Pack %d"), ovi.wServicePackMajor);
                }
            }
            //Windows 98
            else if(ovi.dwMinorVersion == 10) {
                if(ovi.wServicePackMajor == 0) {
                    sprintf(.toStringz(osname), .toStringz("Microsoft Windows 98"));
                } else {
                    sprintf(.toStringz(osname), .toStringz("Microsoft Windows 98 with Servise Pack %d"), ovi.wServicePackMajor);
                }
            }
            //Windows Me
            else if(ovi.dwMinorVersion == 90) {
                if(ovi.wServicePackMajor == 0) {
                    sprintf(.toStringz(osname), .toStringz("Microsoft Windows Me"));
                } else {
                    sprintf(.toStringz(osname), .toStringz("Microsoft Windows Me with Servise Pack %d"), ovi.wServicePackMajor);
                }
            } else {
                sprintf(.toStringz(osname), .toStringz("OSのバージョンが不明です(Windows 95系)。"));
            }
        }
        //あまりあり得ないが、Windows3.1系
        else if(ovi.dwPlatformId == VER_PLATFORM_WIN32s) {
                sprintf(.toStringz(osname), .toStringz("Microsoft Windows 3.1"));
        }
        //Windows NT系
        else if(ovi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
            //Windows NT 3.51
            if(ovi.dwMinorVersion == 51) {
                if(ovi.wServicePackMajor == 0) {
                    sprintf(.toStringz(osname), .toStringz("Microsoft Windows NT 3.51"));
                } else {
                    sprintf(.toStringz(osname), .toStringz("Microsoft Windows NT 3.51 with Servise Pack %d"), ovi.wServicePackMajor);
                }
            }
            //Windows NT 4
            else if(ovi.dwMinorVersion == 0 && ovi.dwMajorVersion == 4) {
                //Workstation
                if(ovi.wProductType == VER_NT_WORKSTATION) {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows NT Workstation 4.0"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows NT Workstation 4.0 with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
                //Server
                else {
                    //Enterprise
                    if(ovi.wSuiteMask & VER_SUITE_ENTERPRISE) {
                        if(ovi.wServicePackMajor == 0) {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows NT Server 4.0 Enterprise Edition"));
                        } else {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows NT Workstation 4.0 Enterprise Edition with Servise Pack %d"), ovi.wServicePackMajor);
                        }
                    }
                    //その他は通常のServerと判断させる
                    else {
                        if(ovi.wServicePackMajor == 0) {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows NT Server 4.0"));
                        } else {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows NT Workstation 4.0 with Servise Pack %d"), ovi.wServicePackMajor);
                        }
                    }                    
                }
            }

            //Windows 2000
            else if(ovi.dwMinorVersion == 0 && ovi.dwMajorVersion == 5)
            {
                //Professional
                if(ovi.wProductType == VER_NT_WORKSTATION) {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows 2000 Professional"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows 2000 Professional with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
                //Server
                else {
                    //Datacenter Server
                    if(ovi.wSuiteMask & VER_SUITE_DATACENTER) {
                        if(ovi.wServicePackMajor == 0) {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows 2000 Datacenter server"));
                        } else {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows 2000 Datacenter server with Servise Pack %d"), ovi.wServicePackMajor);
                        }
                    }
                    //Advanced Server
                    else if(ovi.wSuiteMask & VER_SUITE_ENTERPRISE) {
                        if(ovi.wServicePackMajor == 0) {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows 2000 Advanced server"));
                        } else {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows 2000 Advanced server with Servise Pack %d"), ovi.wServicePackMajor);
                        }
                    }
                    //その他は Serverと判断
                    else {
                        if(ovi.wServicePackMajor == 0) {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows 2000 Server"));
                        } else {
                            sprintf(.toStringz(osname), .toStringz("Microsoft Windows 2000 Server with Servise Pack %d"), ovi.wServicePackMajor);
                        }
                    }
                }
            }

            //Windows XP
            else if(ovi.dwMinorVersion == 1) {
                //Home Edition
                if(ovi.wSuiteMask & VER_SUITE_PERSONAL) {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows XP Home"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows XP Home with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
                //XP Embedded
                else if(ovi.wSuiteMask & VER_SUITE_EMBEDDEDNT) {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows XP Embedded"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows XP Embedded with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
                //Professional Edition
                else {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows XP Professional"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows XP Professional with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
            }

            //Windows Server 2003
            else if(ovi.dwMinorVersion == 2) {
                //Enterprise Edition
                if(ovi.wSuiteMask & VER_SUITE_ENTERPRISE) {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows Server 2003 Enterprise Edition"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows Server 2003 Enterprise Edition with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
                //Datacenter Edition
                else if(ovi.wSuiteMask & VER_SUITE_DATACENTER) {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows Server 2003 Datacenter Edition"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows Server 2003 Datacenter Edition with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
                //Web Edition
                else if(ovi.wSuiteMask & VER_SUITE_BLADE) {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows Server 2003 Web Edition"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows Server 2003 Web Edition with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
                //他は Standard Editionと判断
                else {
                    if(ovi.wServicePackMajor == 0) {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows Server 2003 Standard Edition"));
                    } else {
                        sprintf(.toStringz(osname), .toStringz("Microsoft Windows Server 2003 Standard Edition with Servise Pack %d"), ovi.wServicePackMajor);
                    }
                }
            }
        } else {
            sprintf(.toStringz(osname), "unknown OS");
        }

 		return cast(char[]) std.string.toString(cast(char*) osname);
} else {
		return "unknown OS";
}
	}
	
	
private:
version(Win32){
	static MEMORYSTATUS stat;
} else {
	// lixux ...
}

}



