# Covered by GPL V2.0
# Coded by Carlos del Ojo Elias (deepbit@gmail.com)

import sys
import re

# python 2 and 3: iterator
from builtins import object


class TextParser(object):
    def __init__(self):
        self.string = ""
        self.oldindex = 0
        self.newindex = 0
        self.type = ""
        self.lastFull_line = None
        self.lastline = None

        self.actualIndex = 0

    def __del__(self):
        if self.type == "file":
            self.fd.close()

    def __str__(self):
        return str(self.matches)

    def __iter__(self):
        self.actualIndex = 0
        return self

    def __next__(self):
        try:
            value = self.matches[self.actualIndex]
            self.actualIndex += 1
            return value
        except Exception:
            raise StopIteration

    def setSource(self, t, *args):
        """Se especifica el tipo de entrada. Puede ser fichero o entrada estandard

        Ejemplos: setSource("file","/tmp/file")
                    setSource("stdin")\n"""

        if t == "file":
            self.type = t
            self.fd = open(args[0], "r")
        elif t == "stdin":
            if self.type == "file":
                self.fd.close()
            self.type = t
        elif t == "string":
            if self.type == "file":
                self.fd.close()
            self.type = t
            self.string = args[0]
            self.oldindex = 0
            self.newindex = 0
        else:
            print("Bad argument -- TextParser.setSource()\n")
            sys.exit(-1)

    def seekinit(self):
        self.oldindex = 0
        self.newindex = 0

    def readUntil(self, pattern, caseSens=True):
        "Lee lineas hasta que el patron (pattern) conincide en alguna linea"

        while True:
            if self.readLine() == 0:
                return False
            if self.search(pattern, caseSens) is True:
                break

        return True

    def search(self, pattern, caseSens=True, debug=0):
        "Intenta hacer Matching entre el pattern pasado por parametro y la ultima linea leida"

        if not caseSens:
            self.regexp = re.compile(pattern, re.IGNORECASE)
        else:
            self.regexp = re.compile(pattern)
        self.matches = self.regexp.findall(self.lastline)
        j = 0
        for i in self.matches:
            if not isinstance(i, tuple):
                self.matches[j] = tuple([self.matches[j]])
            j += 1

        #               DEBUG PARA MATCHING
        if debug == 1:
            print(("[", self.lastline, "-", pattern, "]"))
            print((len(self.matches)))
            print((self.matches))

        if len(self.matches) == 0:
            return False
        else:
            return True

    def __getitem__(self, key):
        "Para acceder a cada uno de los patrones que coinciden, esta preparado paragrupos de patrones, no para solo un patron"

        return self.matches[key]

    def skip(self, lines):
        "Salta las lines que se indiquen en el parametro"

        for i in range(lines):
            if self.readLine() == 0:
                return False

        return True

    def readLine(self):
        "Lee la siguiente linea eliminando retornos de carro"

        if self.type == "file":
            self.lastFull_line = self.fd.readline()
        elif self.type == "stdin":
            self.lastFull_line = input()
        elif self.type == "string":
            if self.newindex == -1:
                return 0

            if self.oldindex >= 0:
                self.newindex = self.string.find("\n", self.oldindex, len(self.string))
                if self.newindex == -1:
                    self.newindex = len(self.string) - 1
                self.lastFull_line = self.string[self.oldindex : self.newindex + 1]

                self.oldindex = self.newindex + 1
            else:
                self.lastFull_line = ""

        bytes_read = len(self.lastFull_line)

        s = self.lastFull_line
        self.lastline = s

        if s[-2:] == "\r\n":
            self.lastline = s[:-2]
        elif s[-1:] == "\r" or s[-1:] == "\n":
            self.lastline = s[:-1]

        return bytes_read
