#!/usr/bin/env python

"""
StormSiren
Copyright (C) 2008  Chris Freeze <cfreeze/cfreeze_com\>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""

"""
This is StormSiren a program inspired by the StormSiren application
written by Roy McManus <slorf/users_sourceforge_net>.  Much like the
original StormSiren written by Roy McManus <slorf/users_sourceforge_net>,
this program is a simple script capable of scanning and providing 
notifications of weather bulletins issued by the National 
Weather Service.  StormSiren supports a wide range of paging devices
and filtering of alert types per alert device.  While inspired by 
StormSiren, StormSiren is a complete rewrite that is capable of using
the new CAP/XML feeds provided at http://www.weather.gov/alerts/.

For more information there is see the README.TXT file located in the root
of this directory.
"""

#GLOBAL START
import re
import logging
import sys
#GLOBAL END

#LOCAL START
from WeatherTypes import *
#LOCAL END

#CODE START
class AlertDevice(object):
	def __init__(self, alerts, areas):
		self.__weather_types = WeatherTypes()
		self.__areas = {}
		self.log = logging.getLogger('AlertDevice')

		self.log.setLevel(logging.INFO)
		self.__parse_weather_types(alerts)
		self.__parse_areas(areas)

	def __parse_weather_types(self,weather_types):
		self.log.debug("parsing weather types: -(%s)-" % weather_types)
		try:
			wtypes = weather_types.split(',')
		except Exception,e:
			self.log.error("Unable to weather types in [%s]" % weather_types)
			sys.exit(3)

		for w in wtypes:
			self.addWeatherTypes(w)

	def __parse_areas(self,areas):
		self.log.debug("parsing areas: -(%s)-" % areas)
		try:
			locations = areas.split(':')
		except Exception,e:
			self.log.error("Unable to parse area in [%s]" % areas)
			sys.exit(3)

		for loc in locations:
			self.log.debug("parsing location: -(%s)-" % loc)

			try:
				(spot,state) = loc.split(',')
			except Exception,e:
				self.log.error("Unable to parse location in [%s]" % areas)
				sys.exit(3)

			if(not self.__areas.has_key(state)):
				self.__areas[state] = [spot.lower()]
			else:
				self.__areas[state].append(spot.lower())

	def __str__(self):
		str = "AlertDevice:\n"
		str += "\tWeather Types: %s" % WeatherTypes.toString(self.__weather_types) + "\n"
		str += "Areas:\n"
		for state in self.__areas:
			str += "\n\tState: %s\n\t\t" % state
			str += "\n\t\t".join(self.__areas[state])
		return str

	def display(self):
		print self.__str__()

	def send(self,alert):
		print "Sending Alert: " + alert.id

	def addWeatherTypes(self,wtype):
		wtype = wtype.lower()
		if wtype.find("warning") >= 0:
			self.__weather_types |= WeatherTypes(WARNING)
		if wtype.find("watch") >= 0:
			self.__weather_types |= WeatherTypes(WATCH)
		if wtype.find("advisory") >= 0:
			self.__weather_types |= WeatherTypes(ADVISORY)
		if wtype.find("statement") >= 0:
			self.__weather_types |= WeatherTypes(STATEMENT)
		if wtype.find("forecast") >= 0:
			self.__weather_types |= WeatherTypes(FORECAST)
		if wtype.find("alert") >= 0:
			self.__weather_types |= WeatherTypes(ALERT)

	def isTypeWanted(self, type):
		if (self.__weather_types & type):
			return True
		return False

	def isStateWanted(self,state):
		if(self.__areas.has_key(state)):
			return True
		return False

	def isAreaWanted(self,state,alert_areas):
		if(self.__areas.has_key(state)):
			for area in alert_areas:
				self.log.debug("checking if (%s) is in (%s)" % (area.lower(),self.__areas[state]))
				if(area.lower() in self.__areas[state]):
					self.log.debug("%s IS IN (%s)" % (area.lower(),self.__areas[state]))
					return True
		return False

	def isAlertWanted(self,cap_alert):
		self.log.debug("Testing[%s]: (%s/%i)" % (cap_alert.id, cap_alert.state, cap_alert.type))
		if(self.isTypeWanted(cap_alert.type) and self.isStateWanted(cap_alert.state)):
			self.log.debug("Testing[%s]: type and state match(%s/%i)" % (cap_alert.id, cap_alert.state, cap_alert.type))
			if(self.isAreaWanted(cap_alert.state, cap_alert.areas)):
				self.log.debug("Alert hit on area[%s/%s]: %s" % (cap_alert.state, cap_alert.id, cap_alert.areas))
				return True
			else:
				self.log.debug("Testing[%s]: alert not in watched area(%s/%s)" % (cap_alert.id, cap_alert.state, cap_alert.areas))
		else:
			self.log.debug("Testing[%s]: Either wrong type or state (%s/%i)" % (cap_alert.id, cap_alert.state, cap_alert.type))
		return False
#CODE END

