#!/usr/bin/env python
#
# moviesneak.py
#
# Copyright (c) 2008, Michael Katsevman
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * 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.
#     * Neither the name of the <organization> nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Michael Katsevman ``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 Michael Katsevman 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.
#

from datetime import datetime,timedelta
import sys

def convert_length_to_delta(length):
	length_time = datetime.strptime(length,'%Hhr %Mmin').time()
	length_delta = timedelta(hours=length_time.hour,minutes=length_time.minute)
	return length_delta

def convert_raw_time(times):
	pm = False # the times we are reading are in am, to start

	# if the first time is 1, then we must start at pm
	if times[0].find('1:')!=-1:
		pm = True

	out = []
	for time_r in times:
		time = time_r.rstrip('amp') # strip out am/pm text
		time = datetime.strptime(time,'%H:%M')
		if pm:
			time += timedelta(hours=12)
		out.append(time)

		if time_r[-2:] == 'am': # if there is an explicit am marking, then the following will be in pm
			pm = True
	return out
			



def parse_movies(raw_movies):	
	movies = raw_movies.split('reviews\t')
	for movie in movies[1:]:
		#print movie
		movie = movie.splitlines()
		name = movie[0]
		length_raw = movie[1].split(' - ',1)[0]
		length = convert_length_to_delta(length_raw)

		times_raw = movie[2].split('Rated',1)[0].split()
		start_times = convert_raw_time(times_raw)

		times = [{'start':t,'end':t+length} for t in start_times]

		yield {'name':name,'times':times}



def main():
	threshold = timedelta(seconds=900)
	if len(sys.argv) > 3:
		threshold = timedelta(seconds=sys.argv[2])

	try:
		src = open(sys.argv[1],'r').read()
	except IndexError:
		print 'Usage: moviesneak showtimes_file [optional:threshold in seconds]'
		return 1
	except IOError:
		print 'No such file!'
		return 1
	# warning, ugly algorithm follows
	movies = list(parse_movies(src))
	starts = {}
	ends = {}
	e2s = {}
	
	for i in movies:
		m = i['name']
		for t in i['times']:
			e = t['end']
			s = t['start']
			if e.day > 1:
				continue
			if starts.has_key(s):
				starts[s].append(m)
			else:
				starts[s] = [m]
			if ends.has_key(e):
				ends[e].append(m)
			else:
				ends[e] = [m]
			if e2s.has_key(m):
				e2s[m][e] = s
			else:
				e2s[m] = {e:s}
	
	for s in starts.keys():
		for e in ends.keys():
			 if (s-e).seconds < threshold.seconds or (86399-(e-s).seconds) < threshold.seconds:
		 				 	
			 	print '%s: %s-%s can be followed by:  %s at %s' % (ends[e],
																	e2s[ ends[e][0] ][e].strftime('%H:%M'),
																	e.strftime('%H:%M'),
																	starts[s],
																	s.strftime('%H:%M'))
	return 0				
				#print s,starts[s],'||',e,ends[e]
		
#							print m, '||', m1
#							print t,'+++',t1
			
	#print t[0].isoformat(' '),'-',t[1].isoformat(' ')


if __name__=='__main__':
	sys.exit(main())
