package com.wrox.algorithms.ssearch;

import com.wrox.algorithms.iteration.Iterator;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;

public final class ComparativeStringSearcher {
    /** spodziewana liczba argumentów wywołania aplikacji */
    private static final int NUMBER_OF_ARGS = 2;

    /** nazwa wykorzystywanego zestawu znaków */
    private static final String CHARSET_NAME = "8859_1";

    /** nazwa przeszukiwanego pliku */
    private final String _filename;

    /** poszukiwany wzorzec */
    private final String _pattern;

    public ComparativeStringSearcher(String filename, String pattern) {
        assert filename != null : "nie określono nazwy pliku";
        assert pattern != null : "nie określono poszukiwanego wzorca";

        _filename = filename;
        _pattern = pattern;
    }

    public static void main(String[] args) throws IOException {
        assert args != null : "nie określono argumentów wywołania";

        if (args.length < NUMBER_OF_ARGS) {
            System.err.println("Wywołanie: ComparativeStringSearcher <plik> <wzorzec>");
            System.exit(-1);
        }

        ComparativeStringSearcher searcher = 
                                        new ComparativeStringSearcher(args[0], args[1]);

        searcher.run();
    }

    public void run() throws IOException {
        FileChannel fc = new FileInputStream(_filename).getChannel();
        try {
            ByteBuffer bbuf = fc.map(FileChannel.MapMode.READ_ONLY, 0, (int) fc.size());

            CharBuffer file = Charset.forName(CHARSET_NAME).newDecoder().decode(bbuf);

            System.out.println("Poszukiwanie wzorca " + _pattern + " w pliku " 
                               + _filename+ "' (" + file.length() + ") ...");

            search(new BruteForceStringSearcher(_pattern), file);
            search(new BoyerMooreStringSearcher(_pattern), file);
        } finally {
            fc.close();
        }
    }

    private void search(StringSearcher searcher, CharSequence file) {
        CallCountingCharSequence text = new CallCountingCharSequence(file);
        Iterator i = new StringMatchIterator(searcher, text);

        int occurrence = 0;

        long startTime = System.currentTimeMillis();

        for (i.first(); !i.isDone(); i.next()) {
            ++occurrence;
        }

        long elapsedTime = System.currentTimeMillis() - startTime;

        System.out.println(searcher.getClass().getName()
                + ": wystąpień: " + occurrence
                + ", porównań: " + text.getCallCount()
                + ", czas: " + elapsedTime);
    }
}
