package tiedosto;

import java.io.*;

import fi.jyu.mit.ohj2.*;

import java.util.Map;
import java.util.Scanner;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Iterator;
import java.util.TreeMap;

/**
 * Luokka sanojen esiintymism��rien laskemiseksi.  Toteutettu
 * TreeMap-luokalla ja erillisell� Laskuri-luokalla.
 * @author Vesa Lappalainen
 * @version 1.0, 16.03.2003
 */
public class SanatSortedMap {

    @SuppressWarnings("javadoc")
    public static class Laskuri {
        private int arvo;
        public Laskuri(int arvo) { this.arvo = arvo; }
        public void lisaa() { arvo++; }
        @Override
        public String toString() { return "" + arvo; }
    }

    private Map<String,Laskuri> alkiot = new TreeMap<String,Laskuri>();
    private int sanoja = 0;

    /**
     * Lis�t��n uusi sana rakenteeseen.  Jos on jo, lis�t��n vanhan m��r��,
     * muuten luodaan uusi sana
     * @param s lis�tt�v� sana
     * @example
     * <pre name="test">
     * #import java.io.ByteArrayOutputStream;
     * #import static fi.jyu.mit.ohj2.VertaaTiedosto.*;
     *  ByteArrayOutputStream bs  = new ByteArrayOutputStream();
     *  SanatSortedMap sanat = new SanatSortedMap();
     *  sanat.lisaa("kissa"); sanat.tulosta(bs);
     *  vertaaString(bs,"kissa=1\n") === null;
     *  sanat.lisaa("kissa"); sanat.tulosta(bs);
     *  vertaaString(bs,"kissa=2\n") === null;
     *  sanat.lisaa("kana"); sanat.tulosta(bs);
     *  vertaaString(bs,"kana=1\nkissa=2\n") === null;
     * </pre>
     */
    public void lisaa(String s) {
        sanoja++;
        String sp = s.toLowerCase();
        Laskuri sana = alkiot.get(sp);
        if (sana != null) {
            sana.lisaa();
            return;
        }
        sana = new Laskuri(1);
        alkiot.put(sp, sana);
    }


    /**
     * Tulostetaan koko rakenne tietovirtaan
     * @param os tietovirta johon tulostetaan
     * @example
     * <pre name="test">
     * @example
     * <pre name="test">
     * #import java.io.ByteArrayOutputStream;
     * #import static fi.jyu.mit.ohj2.VertaaTiedosto.*;
     *  ByteArrayOutputStream bs  = new ByteArrayOutputStream();
     *  SanatSortedMap sanat = new SanatSortedMap();
     *  sanat.lisaa("kissa"); sanat.tulosta(bs);
     *  vertaaString(bs,"kissa=1\n") === null;
     * </pre>
     */
    public void tulosta(OutputStream os) {
        @SuppressWarnings("resource")
        PrintStream out = Tiedosto.getPrintStream(os);
        Set<Entry<String, Laskuri>> entrySet = alkiot.entrySet();
        for (Iterator<Entry<String, Laskuri>> i = entrySet.iterator(); i.hasNext();)
            out.println(i.next());
        out.println("Sanoja: " + sanoja);
    }


    /**
     * Pilkotaan rivi sanoiksi ja lis�t��n ne kaikki rakenteeseen
     * @param rivi k�sitelt�v� rivi
     * @example
     * <pre name="test">
     *  ByteArrayOutputStream bs  = new ByteArrayOutputStream();
     *  SanatSortedMap sanat = new SanatSortedMap();
     *  sanat.kasitteleRivi("kissa kana kissa"); sanat.tulosta(bs);
     *  vertaaString(bs,"kana=1\nkissa=2\n") === null;
     *  sanat.kasitteleRivi("kissa istuu kana"); sanat.tulosta(bs);
     *  vertaaString(bs,"istuu=1\nkana=2\nkissa=3\n") === null;
     * </pre>
     */
    public void kasitteleRivi(String rivi) {
        String[] st = rivi.split("[ ,();.:{}\"!?+\\-\\[\\]]+");
        for (String s : st) {
            if (s.startsWith("'") ) s = s.substring(1);
            if ( !s.isEmpty() )
                lisaa(s);
        }        
    }


    /**
     * Luetaan tiedoston kaikki rivit ja k�sitell��n laskemalla kaikki sanat
     * @param tiedostonNimi tiedoston nimi, jota luetaan
     * @throws IOException jos tiedostoa ei voi k�sitell�
     * <pre name="test">
     * #THROWS IOException
     * #import java.io.*;
     *  kirjoitaTiedosto("sanatLueKoe.txt","kissa kana kissa\nkissa istuu kana");
     *  ByteArrayOutputStream bs  = new ByteArrayOutputStream();
     *  SanatSortedMap sanat = new SanatSortedMap();
     *  sanat.lueTiedostoJaLaske("sanatLueKoe.txt"); sanat.tulosta(bs);
     *  vertaaString(bs,"istuu=1\nkana=2\nkissa=3\n") === null;
     *  tuhoaTiedosto("sanatLueKoe.txt");
     * </pre>
     */
    public void lueTiedostoJaLaske(String tiedostonNimi) throws IOException {
        try (Scanner fi = new Scanner(new FileInputStream(new File(tiedostonNimi)))) {
            while ( fi.hasNext() ) {
                String rivi = fi.nextLine();
                kasitteleRivi(rivi);
            }
        }
    }


    /**
     * Testataan SanatSortedMap-luokkaa
     * @param args ei k�yt�ss�
     */
    public static void main(String[] args) {
        SanatSortedMap sanat = new SanatSortedMap();
        sanat.lisaa("kissa");
        sanat.lisaa("kissa");
        sanat.lisaa("koira");
        sanat.tulosta(System.out);
        sanat.kasitteleRivi("kissa, istuu kissa puussa");
        sanat.tulosta(System.out);
    }
}