# Path: filter/manager.py
# class FilterManager(object):
#     def __init__(self):
#         super(FilterManager, self).__init__()
#         self._filters = []
#         self.filter_lock = threading.Lock()
#         self._incomplete_line = ""
# 
#     def add_filter(self, new_filter, output_view):
#         """
#         :type new_filter: serial_filter.FilterFile
#         """
#         filter_args = _FilterArgs(new_filter, output_view)
#         with self.filter_lock:
#             self._filters.append(filter_args)
# 
#     def remove_filter(self, filter_to_remove):
#         """
#         :type filter_to_remove: serial_filter.FilterFile
#         """
#         filter_files = [f.filter_file for f in self._filters]
#         if filter_to_remove in filter_files:
#             with self.filter_lock:
#                 i = filter_files.index(filter_to_remove)
#                 filter_args = self._filters[i]
#                 filter_args.write("Filter Disabled")
#                 self._filters.remove(filter_args)
# 
#     def port_closed(self, port_name):
#         with self.filter_lock:
#             for f in self._filters:
#                 f.write("Disconnected from {}".format(port_name))
# 
#     def filters(self):
#         return [f.filter_file for f in self._filters]
# 
#     def apply_filters(self, text, timestamp=""):
#         if len(self._filters) == 0:
#             return
#         lines = self._split_text(text)
#         if len(lines) == 0:
#             return
# 
#         filters_to_remove = []
#         # Loop through all lines and all filters for matches
#         for line in lines:
#             with self.filter_lock:
#                 for f in self._filters:
#                     if not f.view or not f.filter_file:
#                         continue
# 
#                     if not f.view.is_valid():
#                         filters_to_remove.append(f)
#                     else:
#                         f.apply(line, timestamp)
# 
#         # If any filters have invalid views, remove from the list
#         with self.filter_lock:
#             for f in filters_to_remove:
#                 self._filters.remove(f)
# 
#     def _split_text(self, text):
#         lines = text.splitlines(True)
#         if len(lines) == 0:
#             return lines
# 
#         # Append the last incomplete line to the beginning of this text
#         lines[0] = self._incomplete_line + lines[0]
#         self._incomplete_line = ""
# 
#         # Check if the last line is complete.  If not, pop it from the end of the list and save it as an incomplete line
#         if not lines[-1].endswith("\n"):
#             self._incomplete_line = lines.pop()
#         return lines


import threading
import time
import util
import logger
from filter.manager import FilterManager

            # line and instead add it with the next text received
            newlines = text.count("\n")
            if text[-1] == '\n':
                newlines -= 1
                self._newline = True
            text = text.replace("\n", "\n%s" % timestamp, newlines)

        with self._view_lock:
            util.main_thread(self.view.run_command, "serial_monitor_write", {"text": text})


class SerialMonitor(threading.Thread):
    """
    Thread that controls a stream's read, write, open, close, etc. and outputs the serial info to a sublime view
    :type stream: stream.AbstractStream
    """
    def __init__(self, stream, view, window):
        super(SerialMonitor, self).__init__(name="Thread-{}".format(stream.name))
        self.stream = stream
        self.view = view
        self.window = window
        self.lock = threading.Lock()
        self.running = False
        self.timestamp_logging = False
        self.line_endings = "CRLF"
        self.local_echo = False
        self._text_to_write = []
        self._file_to_write = []
        self._text_lock = threading.Lock()
        self._file_lock = threading.Lock()

# Path: filter/manager.py
# class FilterManager(object):
#     def __init__(self):
#         super(FilterManager, self).__init__()
#         self._filters = []
#         self.filter_lock = threading.Lock()
#         self._incomplete_line = ""
# 
#     def add_filter(self, new_filter, output_view):
#         """
#         :type new_filter: serial_filter.FilterFile
#         """
#         filter_args = _FilterArgs(new_filter, output_view)
#         with self.filter_lock:
#             self._filters.append(filter_args)
# 
#     def remove_filter(self, filter_to_remove):
#         """
#         :type filter_to_remove: serial_filter.FilterFile
#         """
#         filter_files = [f.filter_file for f in self._filters]
#         if filter_to_remove in filter_files:
#             with self.filter_lock:
#                 i = filter_files.index(filter_to_remove)
#                 filter_args = self._filters[i]
#                 filter_args.write("Filter Disabled")
#                 self._filters.remove(filter_args)
# 
#     def port_closed(self, port_name):
#         with self.filter_lock:
#             for f in self._filters:
#                 f.write("Disconnected from {}".format(port_name))
# 
#     def filters(self):
#         return [f.filter_file for f in self._filters]
# 
#     def apply_filters(self, text, timestamp=""):
#         if len(self._filters) == 0:
#             return
#         lines = self._split_text(text)
#         if len(lines) == 0:
#             return
# 
#         filters_to_remove = []
#         # Loop through all lines and all filters for matches
#         for line in lines:
#             with self.filter_lock:
#                 for f in self._filters:
#                     if not f.view or not f.filter_file:
#                         continue
# 
#                     if not f.view.is_valid():
#                         filters_to_remove.append(f)
#                     else:
#                         f.apply(line, timestamp)
# 
#         # If any filters have invalid views, remove from the list
#         with self.filter_lock:
#             for f in filters_to_remove:
#                 self._filters.remove(f)
# 
#     def _split_text(self, text):
#         lines = text.splitlines(True)
#         if len(lines) == 0:
#             return lines
# 
#         # Append the last incomplete line to the beginning of this text
#         lines[0] = self._incomplete_line + lines[0]
#         self._incomplete_line = ""
# 
#         # Check if the last line is complete.  If not, pop it from the end of the list and save it as an incomplete line
#         if not lines[-1].endswith("\n"):
#             self._incomplete_line = lines.pop()
#         return lines


# Path: serial_monitor_thread.py
import threading
import time
import util
import logger
from filter.manager import FilterManager

            # line and instead add it with the next text received
            newlines = text.count("\n")
            if text[-1] == '\n':
                newlines -= 1
                self._newline = True
            text = text.replace("\n", "\n%s" % timestamp, newlines)

        with self._view_lock:
            util.main_thread(self.view.run_command, "serial_monitor_write", {"text": text})


class SerialMonitor(threading.Thread):
    """
    Thread that controls a stream's read, write, open, close, etc. and outputs the serial info to a sublime view
    :type stream: stream.AbstractStream
    """
    def __init__(self, stream, view, window):
        super(SerialMonitor, self).__init__(name="Thread-{}".format(stream.name))
        self.stream = stream
        self.view = view
        self.window = window
        self.lock = threading.Lock()
        self.running = False
        self.timestamp_logging = False
        self.line_endings = "CRLF"
        self.local_echo = False
        self._text_to_write = []
        self._file_to_write = []
        self._text_lock = threading.Lock()
        self._file_lock = threading.Lock()

        self._filter_manager = FilterManager()
