#!/usr/bin/env python

# This file is part of Window-Switch.
# Copyright (c) 2009-2013 Antoine Martin <antoine@nagafix.co.uk>
# Window-Switch is released under the terms of the GNU GPL v3

import time
import os.path

from winswitch.util.simple_logger import Logger
from winswitch.util.common import is_valid_file, load_binary_file, is_valid_dir
logger = Logger("tz_util")

ETC_LOCALTIME = "/etc/localtime"
ETC_CONF_CLOCK = "/etc/conf.d/clock"
ETC_SYSCONFIG_CLOCK = "/etc/sysconfig/clock"
ETC_TIMEZONE = "/etc/timezone"
ZONEINFO_DIRS = ["/usr/share/zoneinfo/", "/usr/local/share/zoneinfo/"]

tz_util = None
def get_tz_util():
	global tz_util
	if not tz_util:
		tz_util = TZ_Util()
	return	tz_util

class TZ_Util:

	def __init__(self):
		Logger(self, log_colour=Logger.HIGHLIGHTED_BLUE)

	def get_timezone_options(self):
		#until the user customizes them, there are the timezones we will show
		#selected pretty much randomly amongst the most popular locations
		zones = [
				"America/Los_Angeles",
				"America/Chicago",
				"America/New_York",
				"Brazil/East",
				"Europe/London",
				"Europe/Paris",
				"Europe/Moscow",
				"Asia/Dubai",
				"Asia/Bangkok",
				"Asia/Singapore",
				"Hongkong",
				"Asia/Shanghai",
				"Japan",
				"Australia/Melbourne",
				"Australia/Sydney"]
		loc_tz = self.get_local_timezone()
		if loc_tz not in zones:
			zones.insert(0, loc_tz)
		return zones;


	def get_timezone_from_filename(self, filename):
		if not filename.startswith("/"):
			return filename
		paths = filename.split(os.path.sep)
		while len(paths)>0 and paths[0]!="zoneinfo":
			paths = paths[1:]
		if paths:
			return "/".join(paths)
		return None

	def find_matching_file(self, size, data, dirs):
		def find_match(d):
			for f in os.listdir(d):
				fp = os.path.join(d, f)
				if is_valid_file(fp):
					#verify file size, then file contents:
					ts = os.path.getsize(fp)
					if ts!=size:
						continue
					compare = load_binary_file(fp)
					if compare==data:
						return	fp
				elif is_valid_dir(fp):
					#recurse down the dir:
					m = find_match(fp)
					if m:
						return m
		for d in dirs:
			if is_valid_dir(d):
				m = find_match(d)
				if m:
					return m
		return None

	def get_local_timezone(self):
		""" this method makes no guarantees
			the returned timezone may not be valid, may be null, etc
		"""
		tz = os.getenv("TZ")
		if tz:
			return self.get_timezone_from_filename(tz)
		if os.name=="posix":
			#get the value directly from one of those files:
			for f in [ETC_TIMEZONE, ETC_CONF_CLOCK]:
				if is_valid_file(f):
					return load_binary_file(f)
			#or lookup the name/value pair in one of those files:
			if is_valid_file(ETC_SYSCONFIG_CLOCK):
				data = load_binary_file(ETC_SYSCONFIG_CLOCK)
				if data:
					for x in data.splitlines():
						parts = x.split("=", 1)
						if len(parts)==2 and parts[0].strip() in ["ZONE", "TIMEZONE"]:
							return parts[1]
			#or use localtime:
			if is_valid_file(ETC_LOCALTIME):
				#absolute path from a softlink:
				if os.path.islink(ETC_LOCALTIME):
					lt = os.path.realpath(ETC_LOCALTIME)
					return self.get_timezone_from_filename(lt)
				#or just find the matching zone file by comparing them all (..):
				size = os.path.getsize(ETC_LOCALTIME)
				if size>0:
					#find the matching file in a zone dir:
					data = load_binary_file(ETC_LOCALTIME)
					m = self.find_matching_file(size, data, ZONEINFO_DIRS)
					if m:
						return	self.get_timezone_from_filename(m)
		return time.tzname[0]

def main():
	logger.slog("get_timezone_options()=%s" % get_tz_util().get_timezone_options())
	logger.slog("get_local_timezone()=%s" % get_tz_util().get_local_timezone())

if __name__ == "__main__":
	main()
