/*****************************************************************************
 * VLCLogScanner.java FVLC VLC Java RMI Binding
 *****************************************************************************
 *
 * @author : Festastic, <info@festastic.com>
 *
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *
 */

package com.festastic.fvlc.util;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;

import org.videolan.jvlc.JVLC;
import org.videolan.jvlc.Logger;
import org.videolan.jvlc.LoggerMessage;

public class VLCLogScanner implements Runnable {

    private static final String          nameKey     = "access_output_udp";
    private static final String          typeKey     = "access out";
    private static final String          msgKey      = "source:";

    private static final long            TIMEOUT     = 5000L;

    private final JVLC                   jvlc;

    private final Map<String, Integer>   sourceMap;
    private String                       sourceKey;

    private final LinkedHashSet<Integer> usedPortSet = new LinkedHashSet<Integer>();
    private int                          lastPort;

    /**
     * Constractor
     *
     * @param JVLC
     *            jvlc
     */
    public VLCLogScanner(final JVLC jvlc) {
        this.jvlc = jvlc;
        sourceMap = new HashMap<String, Integer>();
    }

    /**
     * Sets key for finding source port. key must be same as streaming name.
     *
     * @param String
     *            key
     */
    public void setKey(final String key) {
        this.sourceKey = key;
    }

    /**
     * Removes source port from map.
     *
     * @param String
     *            key
     */
    public void removeSourcePort(final String key) {
        usedPortSet.remove(sourceMap.get(key));
        sourceMap.remove(key);
    }

    /**
     * Returns source port by key.
     *
     * @param String
     *            key
     * @return int source port
     */
    public int getSourcePort(final String key) {
        return sourceMap.get(key) != null ? sourceMap.get(key) : -1;
    }

    public synchronized void run() {
        Logger logger;
        Iterator<LoggerMessage> iterator;
        LoggerMessage lMsg;
        String msg;

        final Calendar currentTime = Calendar.getInstance();

        while (true) {
            logger = jvlc.getLogger();
            iterator = logger.iterator();

            while (iterator.hasNext()) {
                lMsg = iterator.next();
                msg = lMsg.getMessage();

                // System.out.println(msg);

                if (lMsg.getName().equalsIgnoreCase(nameKey) && lMsg.getType().equalsIgnoreCase(typeKey)
                        && lMsg.getMessage().startsWith(msgKey)) {

                    final int sourcePort = Integer.parseInt(msg.substring(msg.indexOf("port") + 4).trim());
                    if (usedPortSet.contains(sourcePort)) {
                        continue;
                    }

                    System.err.println(sourcePort);
                    System.out.println(logger.count());
                    logger.clear();

                    sourceMap.put(sourceKey, sourcePort);
                    usedPortSet.add(sourcePort);
                    lastPort = sourcePort;

                    notifyAll();
                    return;
                }
            }

            logger.clear();

            if (System.currentTimeMillis() - currentTime.getTimeInMillis() > TIMEOUT) {

                final int sourcePort = lastPort + 1;
                sourceMap.put(sourceKey, sourcePort);
                usedPortSet.add(sourcePort);

                logger.clear();

                notifyAll();
                return;
            }
        }
    }
}
