import random
from enum import Enum, unique, auto, IntEnum, IntFlag, Flag
from datetime import date
from itertools import islice

class OrderedEnum(Enum):
	def __ge__(self, other):
		if self.__class__ is other.__class__:
			return self.value >= other.value
		return NotImplemented
	def __gt__(self, other):
		if self.__class__ is other.__class__:
			return self.value > other.value
		return NotImplemented
	def __le__(self, other):
		if self.__class__ is other.__class__:
			return self.value <= other.value
		return NotImplemented
	def __lt__(self, other):
		if self.__class__ is other.__class__:
			return self.value < other.value
		return NotImplemented

#class Week(Enum):
#	Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = 10; Sat = 16; Sun = 17
class Week(OrderedEnum):
	Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5; Sat = 6; Sun = 0
	def isWeekday(self):
		return Week(self.value) <= Week.Fri
	def isWeekend(self):
		return Week.Fri < Week(self.value) 
	@classmethod
	def today(cls, date):
		return cls(date.isoweekday())

day : Week = Week.Tue
print( "weekday:", day.isWeekday() )
print( "weekend:", day.isWeekend() )
print( "today:", Week.today(date.today()))

print( Week.Thu.value == 4 )
print( Week.Thu.name == "Thu" )
print( Week( 4 ) == Week.Thu )
print( Week["Thu"].value == 4 )

if day <= Week.Fri :
	print( "weekday" )
match day:
	case Week.Mon | Week.Tue | Week.Wed | Week.Thu | Week.Fri:
		print( "weekday" )
	case Week.Sat | Week.Sun:
		print( "weekend" )

for day in Week:
	print( day.name, ":", day.value, end=" " )
print( "" )
for day in islice(Week,0,5):
	print( day.name, ":", day.value, end=" " )
print( "" )
for day in islice(Week,5,7):
	print( day.name, ":", day.value, end=" " )
print( "" )
for day in islice(Week,0,7,2):
	print( day.name, ":", day.value, end=" " )
print( "" )

class WeekD(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = 10; Sat = 10; Sun = 10
for day in WeekD:
	print( "Dup", day.name, ":", day.value, end=" " )
print( "" )
for day in WeekD.__members__:
	print( "Dup", day, ":", end=" " )
print( "" )

print( Week["Sat"] )
print( Week( 3 ) )
print( Week["Thu"] )
print( str( Week.Thu ), Week.Thu )
print( Week.Thu.name, Week.Thu.value )
print( isinstance(Week.Fri, Week) )

class WeekE(OrderedEnum): pass
class WeekDay(WeekE): Mon = 1; Tue = 2; Wed = 3; Thu = 4; Fri = 5;
class WeekEnd(WeekE): Sat = 6; Sun = 7
print( "inheritance" )
print( type(WeekE) )
dayI : WeekE = WeekDay.Fri
print( type(dayI), dayI )
dayI = WeekEnd.Sat
print( type(dayI), dayI )

for day in WeekE:
	print( day.name, ":", day.value, end=" " )
print( "" )
for day in WeekDay:
	print( day.name, ":", day.value, end=" " )
print( "" )
for day in WeekEnd:
	print( day.name, ":", day.value, end=" " )
print( "" )

class Week2(Enum): Mon = 1; Tue = 2; Wed = 3; Thu = 10; Fri = auto(); Sat = 4; Sun = auto()
for day in Week2:
	print( day.name, ":", day.value, end=" " )
print( "" )

#@unique
#class DupVal(Enum): ONE = 1; TWO = 2; THREE = 3; FOUR = 3

class RGB(Enum): Red = 1; Green = 2; Blue = 3
for c in RGB:
	print( c.name, ":", c.value )

day = RGB.Red
print( "X", day )
day : Week = RGB.Red
print( "X", day )

class WeekF(Flag): Mon = 1; Tue = 2; Wed = 4; Thu = auto(); Fri = 16; Sat = 32; Sun = 64; \
      Weekday = Mon | Tue | Wed | Thu | Fri; \
      Weekend = Sat | Sun
print( f"0x{repr(WeekF.Weekday.value)} 0x{repr(WeekF.Weekend.value)}" )
day : WeekF = WeekF.Mon | WeekF.Tue
print( type(day) )
for day in WeekF:
	print( f"WeekF {day.name}: {day.value}", end=" " )
print( "" )
weekday = WeekF.Weekday
for day in WeekF.Mon:
	print( f"WeekF.Mon {day.name}:"
           f" {day.value}", end=" " )
print( "" )
for day in weekday:
	print( f"weekday {day.name}:"
           f" {day.value}", end=" " )
print( "" )
weekend = WeekF.Weekend
for day in weekend:
	print( f"weekend {day.name}:"
           f" {day.value}", end=" " )
print( "" )

class WeekA(Flag): Mon = auto(); Tue = auto(); Wed = auto(); Thu = auto(); Fri = auto();  \
							Sat = auto(); Sun = auto(); Weekend = Sat | Sun
for d in WeekA:
	print( f"{d.name}: {d.value}", end=" ")
print( "" )
print(WeekA.Weekend)

class RGBa(Enum): RED = auto(); BLUE = auto(); GREEN = auto()
for c in RGBa:
	print( f"{c.name} {c.value}" )
print( RGBa(1), RGBa(3) )
print( RGBa["RED"], RGBa["GREEN"] )
member = RGBa.RED
print( f"{member.name} {member.value}" )

class Shape(Enum): SQUARE = 2; DIAMOND = 1; CIRCLE = 3; ALIAS_FOR_SQUARE = 2
print(Shape.SQUARE)

print( "" )
class Diff(Enum): Int = 1; Float = 3.5; Str = "ABC"
diffval : Diff = Diff.Int
match diffval:
	case Diff.Int:
		print( "diffval", diffval.value )
	case Diff.Float:
		print( "diffval", diffval.value )
	case Diff.Str:
		print( "diffval", diffval.value )
for i in Diff:
	print( f"Diff type {type(i)}, {i}, {i.name}, {i.value} : " )
print( "\n" )

def by_position(enum_type, position):
	for index, value in enumerate(enum_type):
		if position == index: return value
	raise Exception("by_position out of range")

class Planet(Enum):
	#		   mass (kg)  radius (km)
	MERCURY = ( 0.330E24, 2.4397E6 )
	VENUS   = ( 4.869E24, 6.0518E6 )
	EARTH   = ( 5.976E24, 6.3781E6 )
	MOON	= ( 7.346E22, 1.7380E6 ) # not a planet
	MARS	= ( 0.642E24, 3.3972E6 )
	JUPITER = ( 1898.E24, 71.492E6 )
	SATURN  = ( 568.8E24, 60.268E6 )
	URANUS  = ( 86.86E24, 25.559E6 )
	NEPTUNE = ( 102.4E24, 24.746E6 )
	def __init__(self, mass, radius):
		self.mass = mass		# in kilograms
		self.radius = radius	# in meters
	def surfaceGravity(self):
		# universal gravitational constant  (m3 kg-1 s-2)
		G = 6.67300E-11
		return G * self.mass / (self.radius * self.radius)
	def surfaceWeight(self, otherMass):
		return otherMass * self.surfaceGravity()

class Cats(Enum):
	pass


earthWeight : float = 100
earthMass : float = earthWeight / ( Planet.EARTH.surfaceGravity() )

p = by_position( Planet, random.randrange(8) ) # select a random orbiting body
match p:
	case Planet.MERCURY | Planet.VENUS | Planet.EARTH | Planet.MARS:
		print( f"{p.name} is a rocky planet" )
	case Planet.JUPITER | Planet.SATURN | Planet.URANUS | Planet.NEPTUNE:
		print( f"{p.name} is a gas-giant planet" )
	case _:
		print( f"{p.name} is not a planet" )

for p in Planet:
	print( f"Your weight on {p.name} is {p.surfaceWeight(earthMass):1.1f} kg" )

# Local Variables: #
# tab-width: 4 #
# compile-command: "python3.13 test.py" #
# End: #
