/*
 * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.management.counter.perf;

import sun.management.counter.*;
import java.nio.*;
import java.util.*;
import java.util.regex.*;

public class PerfInstrumentation {
    private ByteBuffer buffer;
    private Prologue prologue;
    private long lastModificationTime;
    private long lastUsed;
    private int  nextEntry;
    private SortedMap<String, Counter>  map;

    public PerfInstrumentation(ByteBuffer b) {
        prologue = new Prologue(b);
        buffer = b;
        buffer.order(prologue.getByteOrder());

        // Check recognized versions
        int major = getMajorVersion();
        int minor = getMinorVersion();

        // Support only 2.0 version
        if (major < 2) {
            throw new InstrumentationException("Unsupported version: " +
                                               major + "." + minor);
        }
        rewind();
    }

    public int getMajorVersion() {
        return prologue.getMajorVersion();
    }

    public int getMinorVersion() {
        return prologue.getMinorVersion();
    }

    public long getModificationTimeStamp() {
        return prologue.getModificationTimeStamp();
    }

    void rewind() {
        // rewind to the first entry
        buffer.rewind();
        buffer.position(prologue.getEntryOffset());
        nextEntry = buffer.position();
        // rebuild all the counters
        map = new TreeMap<>();
    }

    boolean hasNext() {
        return (nextEntry < prologue.getUsed());
    }

    Counter getNextCounter() {
        if (! hasNext()) {
            return null;
        }

        if ((nextEntry % 4) != 0) {
            // entries are always 4 byte aligned.
            throw new InstrumentationException(
                "Entry index not properly aligned: " + nextEntry);
        }

        if (nextEntry < 0  || nextEntry > buffer.limit()) {
            // defensive check to protect against a corrupted shared memory region.
            throw new InstrumentationException(
                "Entry index out of bounds: nextEntry = " + nextEntry +
                ", limit = " + buffer.limit());
        }

        buffer.position(nextEntry);
        PerfDataEntry entry = new PerfDataEntry(buffer);
        nextEntry = nextEntry + entry.size();

        Counter counter = null;
        PerfDataType type = entry.type();
        if (type == PerfDataType.BYTE) {
            if (entry.units() == Units.STRING && entry.vectorLength() > 0) {
                counter = new PerfStringCounter(entry.name(),
                                                entry.variability(),
                                                entry.flags(),
                                                entry.vectorLength(),
                                                entry.byteData());
            } else if (entry.vectorLength() > 0) {
                counter = new PerfByteArrayCounter(entry.name(),
                                                   entry.units(),
                                                   entry.variability(),
                                                   entry.flags(),
                                                   entry.vectorLength(),
                                                   entry.byteData());
           } else {
                // ByteArrayCounter must have vectorLength > 0
                assert false;
           }
        }
        else if (type == PerfDataType.LONG) {
            if (entry.vectorLength() == 0) {
                counter = new PerfLongCounter(entry.name(),
                                              entry.units(),
                                              entry.variability(),
                                              entry.flags(),
                                              entry.longData());
            } else {
                counter = new PerfLongArrayCounter(entry.name(),
                                                   entry.units(),
                                                   entry.variability(),
                                                   entry.flags(),
                                                   entry.vectorLength(),
                                                   entry.longData());
            }
        }
        else {
            // FIXME: Should we throw an exception for unsupported type?
            // Currently skip such entry
            assert false;
        }
        return counter;
    }

    public synchronized List<Counter> getAllCounters() {
        while (hasNext()) {
            Counter c = getNextCounter();
            if (c != null) {
                map.put(c.getName(), c);
            }
        }
        return new ArrayList<>(map.values());
    }

    public synchronized List<Counter> findByPattern(String patternString) {
        while (hasNext()) {
            Counter c = getNextCounter();
            if (c != null) {
                map.put(c.getName(), c);
            }
        }

        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher("");
        List<Counter> matches = new ArrayList<>();


        for (Map.Entry<String,Counter> me: map.entrySet()) {
            String name = me.getKey();

            // apply pattern to counter name
            matcher.reset(name);

            // if the pattern matches, then add Counter to list
            if (matcher.lookingAt()) {
                matches.add(me.getValue());
            }
        }
        return matches;
    }
}
