#!/usr/bin/python3
"""

Käyttöohje:
Lisää kaikki sanat self.addSearchWord-metodilla kokonaisuudessaan nodeihin
Sen jälkeen trimmaa trimNodes-metodilla hakusanat, jotta turhat valinnat lähtevät pois.

param on muotoa: '(tekstiä1||tekstiä2)&&(~"tekstiä3"" lisää tekstiä 3:n")^Tekstiä4'

Tehdään parametrista seuraava Array...
['tekstiä1','tekstiä2','tekstiä3 lisää tekstiä 3:n','Tekstiä4']

...
Ja seuraava funktio:
( P0 | P1 )&(~ P2 ^ P3 )

Elikkä ...
P0 == Array[0]
P1 == Array[1]
P2 == Array[2]
P3 == Array[3]

Etsitään tiedostosta merkkijonot P0 ... P3, (Jos P0 löytyy, P1 ei löydy, P2 ei löydy ja P3 löytyy), ja ratkaistaan esimerkkifunktio:
( P0 | P1 )&(~ P2 ^ P3 ) => (True|False)&(~False^True) => (True)&(True^True) => True&(False) => False

Tuosta seuraa, että ei tulosteta tiedostonnimeä, jos olisi tullut True, niin olisi tulostettu tiedostonnimi-rivillään.

"""
import sys
import getparameter
import logging
import os
import tempfile
import zipfile
MAXFILESIZE=1024*1024*1024

debug = False
class BooleanGrep:                                                              # Riippuu kirjainkoosta eli T != t
    def __init__(self,params:str,filename:str,charSpace:str="",casesensitive:bool=False):
        self.formula=getparameter.SolveFormulaParams(params)
        solveformulaPrms=self.formula
        if debug:
            print("PARAMETRIT=")
            #print(self.solveformulaPrms.function,solveformulaPrms.params)
            print(solveformulaPrms.function,solveformulaPrms.params)
        prms=solveformulaPrms.params
        self.params=solveformulaPrms.params
        self.function=solveformulaPrms.function
        self.ignoreCase=not casesensitive
        self.filename=filename
        self.tempdir=[]


    #def searchWord(self,wordsnetsIdx):
    def searchWords(self):#,wordsIdx):
        if os.path.isfile(self.filename):
            fo = open(self.filename,"rb")
            txtidx=0
            stats=os.stat(self.filename)
            buf=fo.read(4)
            fo.close()
            idx=0
            while idx<len(buf):
                if buf[idx]!=[ 80,75,3,4][idx]:
                    if debug:
                        print("EI OLE ZIP-tiedosto suurella todennäköisyydellä:")
                    #quit()
                    break
                idx+=1
            if debug:
                print("idx=",idx)
            if idx==4:
                if self.tempdir==[]:
                    #self.tempdir.append(tempfile.mkdtemp(prefix="bgrep_"+os.path.basename(self.filename)+"_",suffix='.zipd'))
                    #print("self.tempdir=",self.tempdir)
                    try:
                        if debug:
                            print("self.filenam=",self.filename)
                        zfile=zipfile.ZipFile(self.filename)
                        if debug:
                            print("HMM")
                        for zinfo in zfile.infolist(): #zfile.getinfo():
                            if debug:
                                print("zinfo")
                            #statZipFile=os.stat(fnames)
                            try:
                                if zinfo.file_size<MAXFILESIZE:
                                    #
                                    fo=zfile.open(zinfo.filename)
                                    self.buf=fo.read(MAXFILESIZE).decode("utf-8")
                                    fo.close()
                                    try:
                                        #self.buf=self.buf.decode("utf-8")
                                        if debug:
                                            print("ZIP BUF=",zinfo.filename,self.buf)
                                        if self.ignoreCase:
                                            self.buf=self.buf.lower()
                                        res=[]
                                        if self.ignoreCase:
                                            for param in self.params:
                                                res.append(param.lower() in self.buf)
                                            pass
                                        else:
                                            for param in self.params:
                                                res.append(param in self.buf)
                                            pass


                                        val=""
                                        for value in res:
                                            if value:
                                                val+="T"
                                            else:
                                                val+="F"
                                        res=self.formula.solveFormula(self.formula.function,val)
                                        if res=="T":
                                            return "T"
                                    except Exception as e:
                                        print("ZIP-tiedostossa oleva:",zinfo.filename,"-tiedosto ei ole utf-8-formaatissa.",file=sys.stderr);
                                        print("Tai tuli jotain muuta ongelmaa:",e,file=sys.stderr);
                                pass
                            except:
                                pass
                    except Exception as e:
                        print("EI OLLUT ZIPPI KUITENKAAN???:",e,file=sys.stderr)#os.stderr)
                if debug:
                    print("ZIP QUIT")
                    #quit()
                return "F"

            if debug:
                print("bgrep quit rivi 73")
            #quit()
            try:
                fo=open(self.filename,"r")
                self.buf=fo.read(MAXFILESIZE)
                #if os.statsfilesize(self.filename)
                fo.close()
                if self.ignoreCase:
                    self.buf=self.buf.lower()
                if debug:
                    print("BUF")
                    print(self.buf)
                    print(len(self.buf))
                res=[]
                if self.ignoreCase:
                    for param in self.params:
                        res.append(param.lower() in self.buf)
                else:
                    for param in self.params:
                        res.append(param in self.buf)
                val=""
                for value in res:
                    if value:
                        val+="T"
                    else:
                        val+="F"
                res=self.formula.solveFormula(self.formula.function,val)
                #if res=="T":
                #            print(bgrep.filename)
            except Exception as e:
                print("rivi noin 162:",e,file=sys.stderr)
                res="E"
                pass
            return res

if __name__=='__main__':
    if len(sys.argv)>1:
        if debug:
            print("sys.argv",sys.argv)
        uncase=True
        xparam=0
        addparam=1
        while addparam<len(sys.argv):
            xparam=addparam
            if sys.argv[addparam]=='--ignore-case' or sys.argv[addparam]=='-i':
                if debug:
                    print("casesensitive")
                uncase=False
                addparam+=1
            if sys.argv[addparam]=="--debug" or sys.argv[addparam]=='-d':
                debug=True
                if debug:
                    print("DEBUGMODE=True")
                addparam+=1
                if sys.argv[addparam]=='--no-ignore-case' or sys.argv[addparam]=='-n':
                    if debug:
                        print("caseinsensitive")
                    uncase=True
                    addparam+=1
            if xparam==addparam:
                #addparam-=1
                break
        if debug:

            print("PARAMS=",sys.argv,addparam)
            print("PRMS=",sys.argv[addparam])
            #quit()
        #
        #print(len(sys.argv),addparam)
        #bgrep=BooleanGrep(sys.argv[addparam],sys.argv[addparam+1],casesensitive=uncase)
        bgrep=BooleanGrep(sys.argv[addparam],"",casesensitive=uncase)
        for bgrepPrm in bgrep.params:
            #if debug:
            if debug:
                print("bgrepPrm=",bgrepPrm)
            if bgrepPrm=="":
                print("Have empty parrams: F=",bgrep.function,", Params=",bgrep.params,file=sys.stderr)
                quit()




        if len(sys.argv)<=addparam+1:
            #print("PARAMETRIT == LEN(sys.argv)")
            bgrep=BooleanGrep(sys.argv[addparam],"",casesensitive=uncase)
            bgrep.filename="tests/source.txt"
            if debug:
                print("PARAMETRIT == LEN(sys.argv)")
                print(bgrep.params,bgrep.function)
            for line in sys.stdin:
                if 'Exit' == line.rstrip():
                    break
                bgrep.filename=line.strip()
                res=bgrep.searchWords()
                """
                val=""
                for value in res:
                    if value:
                        val+="T"
                    else:
                        val+="F"
                res=bgrep.formula.solveFormula(bgrep.formula.function,val)
                """
                if res=="T":
                    print(bgrep.filename.strip())
            """
            for bgrepPrm in bgrep.params:
                #if debug:
                if debug:
                    print("bgrepPrm=",bgrepPrm)
                if bgrepPrm=="":
                    print("Have empty parrams: F=",bgrep.function,", Params=",bgrep.params,file=sys.stderr)
                    quit()
            """
        else:
            #bgrep=BooleanGrep(sys.argv[addparam],sys.argv[1],casesensitive=uncase)
            while addparam+1<len(sys.argv):
                bgrep.filename=sys.argv[addparam+1]   #,casesensitive=uncase)
                res=bgrep.searchWords()
                if res=="T":
                    print(bgrep.filename)
                #elif len(sys.argv)==2:
                addparam+=1

    else:
        print("SYNOPSIS")
        print("         search [OPTION...] PATTERN [FILENAMES...]")
        print("         search [OPTION...] PATTERN")
        print()
        print("OPTIONS")
        print()
        print("     Matching Control")
        print("         -i, --ignore-case")
        print("             Make search by casesensitive txt. Example: 'program' != 'Program'")
        print()
        print("         -n, --no-ignore-case")
        print("             Do  not  ignore  case  distinctions  in patterns and input data.  This is the default.")
        #print("             This option is useful for passing to shell scripts that already use -i,")
        #print("             to cancel its effects because the two options override each other.")
        print()
        """
        print("         -f FILE --file=FILE")
        print("             Obtain patterns from FILE, one per line.")
        print("             If this option is used multiple times  or  is  combined  with  the  -e  (--regexp)")
        print("             option, search for all patterns given. ")
        print("             The empty file contains zero patterns, and therefore matches nothing.")
        print()
        """
        #print()
        print("         -z --zip")
        print("             Find also from zip-files.")
        print()
        print("         -d --debug")
        print("             Sets to debug-mode.")
        print()
        print("         IF no filenames in parameters you most give filenames by standard out (/dev/stdout).")
        print("             Example:")
        print("                 ls *.txt|bgrep -i 'PATTERN'")
        print()
        print("PATTERN")
        print("         'text'")
        print("             Example:")
        print("                 echo 'words3words2 ' >test.txt ")
        print("                 echo 'words1words4words3' > test2.txt")
        print("                 ls *.txt|search '~words1 & words2 | words3 ^ words4'")
        print("     PRINTS:")
        print("                 test.txt")
        print()
        print("                 ls *.txt|search 'word'")
        print("     PRINTS:")
        print("                 test.txt")
        print("                 test2.txt")
        print()
        print("EXPLANATION:")
        print("     PATTERN: ~words1 & words2 | words 3 ^ words4")
        print("                        TEXT: test.txt")
        print("                        words3,words2 -> T,True, words1,words4 -> F,False")
        print("                        ~F & T | T ^ F")
        print("                  ->    not F and T or T xor F")
        print("                  ->    T and T or T xor F")
        print("                  ->    T or T")
        print("                  ->    T")
        print("                  ->    prints filename:")
        print("                  ->    test.txt")
