###############################################################################
#                                                                             #
# Fireinfo                                                                    #
# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org)                       #
#                                                                             #
# This program is free software: you can redistribute it and/or modify        #
# it under the terms of the GNU General Public License as published by        #
# the Free Software Foundation, either version 3 of the License, or           #
# (at your option) any later version.                                         #
#                                                                             #
# This program is distributed in the hope that it will be useful,             #
# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
# GNU General Public License for more details.                                #
#                                                                             #
# You should have received a copy of the GNU General Public License           #
# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
#                                                                             #
###############################################################################

import os

from . import system

PROC_CPUINFO = "/proc/cpuinfo"

class CPU(object):
	"""
		A class that represents the first CPU in a system.

		We get all information form the first CPU (or core) and assume that
		all other ones are equal.
	"""

	__cpuinfo = {}

	def __init__(self):
		"""
			Initialize this class by reading all data from /proc/cpuinfo.
		"""
		self.__cpuinfo = self.read_cpuinfo()

	@property
	def system(self):
		return system.System()

	@staticmethod
	def read_cpuinfo():
		"""
			Read information from PROC_CPUINFO and store
			it into a dictionary cpuinfo.
		"""
		cpuinfo = {}

		f = open(PROC_CPUINFO)
		while True:
			line = f.readline()

			if not line:
				break

			try:
				key, val = line.split(":", 1)
			except ValueError:
				# We got a line without key, pass that.
				pass

			key = key.strip().replace(" ", "_")
			val = val.strip()

			cpuinfo[key] = val

		f.close()

		return cpuinfo

	@property
	def bogomips(self):
		"""
			Return the bogomips of this CPU.
		"""
		bogomips = None

		for key in ("bogomips", "BogoMIPS"):
			try:
				bogomips = self.__cpuinfo[key]
			except KeyError:
				continue

		if bogomips:
			return float(bogomips)

	@property
	def model(self):
		"""
			Return the model id of this CPU.
		"""
		try:
			model = int(self.__cpuinfo["model"])
		except KeyError:
			model = None

		return model

	@property
	def model_string(self):
		"""
			Return the model string of this CPU.
		"""
		for key in ("model_name", "Processor"):
			try:
				return self.__cpuinfo[key]
			except KeyError:
				pass

	@property
	def vendor(self):
		"""
			Return the vendor string of this CPU.
		"""
		try:
			vendor = self.__cpuinfo["vendor_id"]
		except KeyError:
			if self.system.arch.startswith("arm"):
				vendor = "ARM"
			else:
				vendor = ""

		return vendor

	@property
	def stepping(self):
		"""
			Return the stepping id of this CPU.
		"""
		try:
			stepping = int(self.__cpuinfo["stepping"])
		except KeyError:
			stepping = None

		return stepping

	@property
	def flags(self):
		"""
			Return all flags of this CPU.
		"""
		try:
			flags = self.__cpuinfo["flags"]
		except KeyError:
			flags = self.__cpuinfo["Features"]

		return flags.split()

	@property
	def speed(self):
		"""
			Return the speed (in MHz) of this CPU.
		"""
		try:
			speed = float(self.__cpuinfo["cpu_MHz"])
		except KeyError:
			speed = 0

		return speed

	@property
	def family(self):
		"""
			Return the family id of this CPU.
		"""
		try:
			family = int(self.__cpuinfo["cpu_family"])
		except KeyError:
			family = None

		return family
	
	@property
	def count(self):
		"""
			Count number of CPUs (cores).
		"""
		return os.sysconf("SC_NPROCESSORS_ONLN")


if __name__ == "__main__":
	c = CPU()

	print("Vendor:", c.vendor)
	print("Model:", c.model)
	print("Stepping:", c.stepping)
	print("Flags:", c.flags)
	print("Bogomips:", c.bogomips)
	print("Speed:", c.speed)
	print("Family:", c.family)
	print("Count:", c.count)
	print("Model string:", c.model_string)
