package com.tagtraum.perf.gcviewer.imp;

import com.tagtraum.perf.gcviewer.DataReader;
import com.tagtraum.perf.gcviewer.GCModel;
import com.tagtraum.perf.gcviewer.GCEvent;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;

/**
 * Parses -verbose:gc output from Sun JDK 1.4.0.
 *
 * Date: Jan 30, 2002
 * Time: 5:15:44 PM
 * @author <a href="mailto:hs@tagtraum.com">Hendrik Schreiber</a>
 * @version $Id: $
 */
public class DataReaderSun1_4_0 extends AbstractDataReaderSun implements DataReader {

    private boolean firstLine;
    private BufferedReader in;

    public DataReaderSun1_4_0(InputStream in) {
        this.in = new BufferedReader(new InputStreamReader(in));
    }

    public GCModel read() throws IOException {
        try {
            firstLine = true;
            GCModel model = new GCModel();
            model.setFormat(GCModel.Format.SUN_X_LOG_GC);
            String line = null;
            while ((line = in.readLine()) != null) {
                try {
                    model.add(parseLine(line));
                } catch (ParseException pe) {
                    pe.printStackTrace();
                    System.out.println(pe.getMessage());
                }
            }
            return model;
        } finally {
            if (in != null) try {
                in.close();
            } catch (IOException ioe) {
            }
        }
    }

    private GCEvent parseLine(String line) throws ParseException {
        GCEvent event = new GCEvent();
        try {
            int index = line.indexOf(':');
            if (index == -1) throw new ParseException("Error parsing entry: " + line);
            event.setTimestamp(Double.parseDouble(line.substring(0, index).replace(',', '.')));
            StringTokenizer st = new StringTokenizer(line.substring(index + 1), " ,->()K\r\n:[]");
            String token = st.nextToken();
            if (token.equals("Full") && st.nextToken().equals("GC")) {
                event.setType(GCEvent.Type.FULL_GC);
            } else if (token.equals("Inc") && st.nextToken().equals("GC")) {
                event.setType(GCEvent.Type.INC_GC);
            } else if (token.equals("GC")) {
                event.setType(GCEvent.Type.GC);
            } else {
                throw new ParseException("Error parsing entry: " + line);
            }
            setMemoryAndPauses(event, line);
            // debug
            //System.out.println("Parsed: " + event);
            //System.out.println("Real  : [" + line + "]");
            return event;
        } catch (RuntimeException rte) {
            throw new ParseException("Error parsing entry: " + line + ", " + rte.toString());
        }
    }

}
