# Path: analyzer/utils.py
# def window(seq, n=2):
# 	"""Returns a sliding window (of width n) over data from the iterable"""
# 	"   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
# 	it = iter(seq)
# 	result = tuple(islice(it, n))
# 	if len(result) == n:
# 		yield result
# 	for elem in it:
# 		result = result[1:] + (elem,)
# 		yield result
# 
# Path: analyzer/alignment_utils.py
# class Alignment(object):
# 	old_vertical_index = None
# 	old_horizontal_index = None
# 
# 	def __init__(self, alignment_list, vertical_index, horizontal_index, grid, traceback, subtitles=None):
# 		self.alignment_list = alignment_list
# 		self.vertical_index = vertical_index
# 		self.horizontal_index = horizontal_index
# 		self.grid = grid
# 		self.traceback = traceback
# 		self.subtitles = subtitles
# 
# Path: analyzer/script_entity.py
# class ScriptEntity(Model):
# 	def __init__(self, character, text, type="speech"):
# 		self.character = character
# 		self.type = type
# 		self.original_text = text
# 
# 		self.text = text.rstrip().replace('\n', ' ') if type == 'speech' else text
# 
# 	def __str__(self):
# 		return "type: {}, character: {}, text: \"{}\"".format(self.type, self.character, self.text)
# 
# 	def __repr__(self):
# 		return self.__str__()
# 
# 	@classmethod
# 	def from_dict(cls, data, from_camel=True):
# 		d = Model.from_dict(data, from_camel)
# 		return cls(d.get("character"), d.get("text"), type=d.get("type"))
# 
# 	@classmethod
# 	def from_dicts(cls, data, from_camel=True):
# 		return [cls.from_dict(d) for d in data]
# 
# Path: analyzer/string_utils.py
# def remove_punctuation(text):
# 	exclude = set(string.punctuation)
# 	exclude.add("'")
# 
# 	characters = []
# 	for character in text:
# 		if character not in exclude:
# 			characters.append(character)
# 		else:
# 			characters.append(" ")
# 
# 	cleaned_text = "".join(characters)
# 	var = re.sub(' +', ' ', cleaned_text)
# 
# 	return var


import editdistance
import numpy as np
from scipy.spatial import distance as dist
from tqdm import tqdm
from copy import deepcopy
from itertools import groupby
from analyzer.utils import window
from analyzer.alignment_utils import Alignment
from analyzer.script_entity import ScriptEntity
from analyzer.string_utils import remove_punctuation
		logger.add("\"{}\" {}/{} ({:.1f}%)".format(current_subtitle.text, matches_count, possible_matches,
		                                           match_in_percent))
		logger.add("{}".format([speech.text for speech in speeches_from_matches(matches)]))
		logger.add("{}".format(formatted_matches))
		logger.add("\n")

		prev_index = i
		current_subtitle = subtitle
		current_subtitle_index += 1

	subtitles_length = len(subtitles)
	merged_subtitles_count = len([subtitle for subtitle in subtitles if subtitle.character is not None])
	success_rate = merged_subtitles_count / subtitles_length * 100
	logger.add("Success Rate: {} of {} ~ {:.1f}%".format(merged_subtitles_count, subtitles_length, success_rate))

	return subtitles


def perform(speeches, subtitles, logger, distance_function=binary_distance, verbose=False):
	subtitles = deepcopy(subtitles)
	speeches = deepcopy(speeches)

	subtitle_index = map_words_to_entity(subtitles, lambda entity: prepare_text(entity.text))
	speeches_index = map_words_to_entity(speeches, lambda entity: prepare_text(entity.text))

	print("Words\nSubtitles:\t{}\nScripts:\t{}".format(len(subtitle_index), len(speeches_index)))

	grid, traceback = dtw(subtitle_index, speeches_index, distance_function, logger)

	alignment_list = calculate_backtrace(traceback)

# Path: analyzer/utils.py
# def window(seq, n=2):
# 	"""Returns a sliding window (of width n) over data from the iterable"""
# 	"   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
# 	it = iter(seq)
# 	result = tuple(islice(it, n))
# 	if len(result) == n:
# 		yield result
# 	for elem in it:
# 		result = result[1:] + (elem,)
# 		yield result
# 
# Path: analyzer/alignment_utils.py
# class Alignment(object):
# 	old_vertical_index = None
# 	old_horizontal_index = None
# 
# 	def __init__(self, alignment_list, vertical_index, horizontal_index, grid, traceback, subtitles=None):
# 		self.alignment_list = alignment_list
# 		self.vertical_index = vertical_index
# 		self.horizontal_index = horizontal_index
# 		self.grid = grid
# 		self.traceback = traceback
# 		self.subtitles = subtitles
# 
# Path: analyzer/script_entity.py
# class ScriptEntity(Model):
# 	def __init__(self, character, text, type="speech"):
# 		self.character = character
# 		self.type = type
# 		self.original_text = text
# 
# 		self.text = text.rstrip().replace('\n', ' ') if type == 'speech' else text
# 
# 	def __str__(self):
# 		return "type: {}, character: {}, text: \"{}\"".format(self.type, self.character, self.text)
# 
# 	def __repr__(self):
# 		return self.__str__()
# 
# 	@classmethod
# 	def from_dict(cls, data, from_camel=True):
# 		d = Model.from_dict(data, from_camel)
# 		return cls(d.get("character"), d.get("text"), type=d.get("type"))
# 
# 	@classmethod
# 	def from_dicts(cls, data, from_camel=True):
# 		return [cls.from_dict(d) for d in data]
# 
# Path: analyzer/string_utils.py
# def remove_punctuation(text):
# 	exclude = set(string.punctuation)
# 	exclude.add("'")
# 
# 	characters = []
# 	for character in text:
# 		if character not in exclude:
# 			characters.append(character)
# 		else:
# 			characters.append(" ")
# 
# 	cleaned_text = "".join(characters)
# 	var = re.sub(' +', ' ', cleaned_text)
# 
# 	return var


# Path: analyzer/dtw_merger.py
import editdistance
import numpy as np
from scipy.spatial import distance as dist
from tqdm import tqdm
from copy import deepcopy
from itertools import groupby
from analyzer.utils import window
from analyzer.alignment_utils import Alignment
from analyzer.script_entity import ScriptEntity
from analyzer.string_utils import remove_punctuation

		logger.add("\"{}\" {}/{} ({:.1f}%)".format(current_subtitle.text, matches_count, possible_matches,
		                                           match_in_percent))
		logger.add("{}".format([speech.text for speech in speeches_from_matches(matches)]))
		logger.add("{}".format(formatted_matches))
		logger.add("\n")

		prev_index = i
		current_subtitle = subtitle
		current_subtitle_index += 1

	subtitles_length = len(subtitles)
	merged_subtitles_count = len([subtitle for subtitle in subtitles if subtitle.character is not None])
	success_rate = merged_subtitles_count / subtitles_length * 100
	logger.add("Success Rate: {} of {} ~ {:.1f}%".format(merged_subtitles_count, subtitles_length, success_rate))

	return subtitles


def perform(speeches, subtitles, logger, distance_function=binary_distance, verbose=False):
	subtitles = deepcopy(subtitles)
	speeches = deepcopy(speeches)

	subtitle_index = map_words_to_entity(subtitles, lambda entity: prepare_text(entity.text))
	speeches_index = map_words_to_entity(speeches, lambda entity: prepare_text(entity.text))

	print("Words\nSubtitles:\t{}\nScripts:\t{}".format(len(subtitle_index), len(speeches_index)))

	grid, traceback = dtw(subtitle_index, speeches_index, distance_function, logger)

	alignment_list = calculate_backtrace(traceback)

	alignment = Alignment(alignment_list, subtitle_index, speeches_index, grid, traceback, subtitles)