/** BEGIN COPYRIGHT BLOCK
 * Copyright (C) 2001 Sun Microsystems, Inc.  Used by permission.
 * Copyright (C) 2005 Red Hat, Inc.
 * All rights reserved.
 * 
 * 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; version 2
 * of the License.
 * 
 * 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.
 * 
 * END COPYRIGHT BLOCK **/
package com.netscape.management.admserv.logging;

import java.io.*;
import java.util.*;
import java.net.*;
import javax.swing.table.*;
import com.netscape.management.client.comm.*;
import com.netscape.management.client.console.*;
import com.netscape.management.client.logging.*;
import com.netscape.management.client.util.*;
import com.netscape.management.admserv.*;

public class ErrorLogViewerModel extends LogViewerModel {
    ConsoleInfo _consoleInfo;
    String _url;
    String _username;
    String _password;
    int _logLength = 0;
    private boolean _isInitialized = false;
    private boolean _logLengthAvailable = false;
    private boolean _logLengthCalculating = false;
    StringBuffer _logLengthStringBuffer = null;
    public static ResourceSet _resource = AdminServer._resource;

    public ErrorLogViewerModel(ConsoleInfo consoleInfo, String url) {
        super();
        _consoleInfo = consoleInfo;
        _url = _consoleInfo.getAdminURL() + url;
        _username = _consoleInfo.getAuthenticationDN();
        _password = _consoleInfo.getAuthenticationPassword();

        addColumn(_resource.getString("log", "lineno"));
        addColumn(_resource.getString("log", "datetime"));
        addColumn(_resource.getString("log", "severity"));
        addColumn(_resource.getString("log", "details"));

        _isInitialized = true;
    }

    public void populateRows(int rowStartIndex, int numRows) {
        Debug.println(6,
                "ErrorLogViewer: populateRows " + rowStartIndex +
                " to " + (rowStartIndex + numRows));
        try {
            URL url = new URL(_url + "?op=read" + "&start=" +
                    rowStartIndex + "&stop=" +
                    (rowStartIndex + numRows) + "&name=error");
            HttpManager _httpManager = new HttpManager();
            ErrorLogDataClient commClient =
                    new ErrorLogDataClient(_username, _password);
            _httpManager.get(url, commClient, (ILogViewerModel) this,
                    CommManager.ASYNC_RESPONSE |
                    CommManager.FORCE_BASIC_AUTH);
        } catch (Exception e) {
            Debug.println(4, "ErrorLogViewer: populateRows() " + e);
        }
    }



    /**
       * Returns the number of rows in log file
       */
    public int getLogLength() {
        if (!_isInitialized)
            return -1;

        long _currentTimeMillis = System.currentTimeMillis();
        if (((_currentTimeMillis - _lastLogLengthCheckTime) >
                UPDATE_INTERVAL) && !_logLengthCalculating) {
            _lastLogLengthCheckTime = _currentTimeMillis;
            try // to update _logLength
            {
                _logLengthCalculating = true;
                _logLengthAvailable = false;
                _logLengthStringBuffer = new StringBuffer();
                URL url = new URL(_url + "?op=count" + "&name=error");
                HttpManager _httpManager = new HttpManager();
                LogLengthCommClient commClient =
                        new ErrorLogLengthCommClient(_username, _password);
                _httpManager.get(url, commClient, _logLengthStringBuffer,
                        CommManager.ASYNC_RESPONSE |
                        CommManager.FORCE_BASIC_AUTH);
            } catch (Exception e) {
                _logLengthCalculating = false;
                Debug.println(4, "ErrorLogViewer: getLogLength(): " + e);
            }
        }

        if (_logLengthAvailable) {
            try {
                _logLength = Integer.parseInt(
                        _logLengthStringBuffer.toString());
                Debug.println(6,
                        "ErrorLogViewer: _logLength=" + _logLength);
            } catch (NumberFormatException e) {
                Debug.println(4,
                        "ErrorLogViewer: Cannot convert log length: " +
                        _logLengthStringBuffer.toString());
            }
        }

        return _logLength;
    }

    class ErrorLogDataClient extends AbstractCommClient {
        final int STATE_START = 0;
        final int STATE_DATETIME = 1;
        final int STATE_SEVERITY = 2;
        final int STATE_DETAIL = 3;
        protected LogViewerModel _model;

        public ErrorLogDataClient(String username, String password) {
            super(username, password);
        }

        class ErrorLogData {
            StringBuffer datetime = new StringBuffer();
            StringBuffer severity = new StringBuffer();
            StringBuffer detail = new StringBuffer();
        }


        protected ErrorLogData parse(String logEntry) {
            StringBuffer buffer = new StringBuffer(logEntry);
            ErrorLogData data = new ErrorLogData();
            int bufferLength = buffer.length();
            int state = STATE_START;
            char character;

            for (int index = 0; index < bufferLength; index++) {
                character = buffer.charAt(index);
                switch (state) {
                case STATE_START:
                    if (character == '[')
                        state = STATE_DATETIME;
                    break;

                case STATE_DATETIME:
                    if (character == ']')
                        state = STATE_SEVERITY;
                    else
                        data.datetime.append(character);
                    break;

                case STATE_SEVERITY:
                    if (character == ']')
                        state = STATE_DETAIL;
                    else if (character != '[')
                        data.severity.append(character);
                    break;

                case STATE_DETAIL:
                    data.detail.append(character);
                    break;
                }
            }
            return data;
        }

        public void replyHandler(InputStream replyStream, CommRecord cr) {
            BufferedReader replyBuffer = new BufferedReader(
                    new InputStreamReader(replyStream));
            ILogViewerModel model = (ILogViewerModel) cr.getArg();
            int rowOffset = model.getRowOffset();
            int bufferLength = model.getBufferLength();
            String logEntry = null;
            for (int rowIndex = 0; rowIndex < bufferLength; rowIndex++) {
                try {
                    logEntry = replyBuffer.readLine();
                } catch (Exception e) {
                    Debug.println(4,
                            "ErrorLogViewer: repxlyHandler() " + e);
                }
                if (logEntry != null) {
                    ErrorLogData d = parse(logEntry);
                    model.setValueAt(
                            Integer.toString(rowOffset + rowIndex),
                            rowIndex, 0);
                    model.setValueAt(d.datetime, rowIndex, 1);
                    model.setValueAt(d.severity, rowIndex, 2);
                    model.setValueAt(d.detail, rowIndex, 3);
                } else {
                    break;
                }
            }
            finish();
        }


        public synchronized void finish() {
            super.finish();
            ErrorLogViewerModel.this.tableDataChanged();
        }
    }

    public class ErrorLogLengthCommClient extends LogLengthCommClient {
        public ErrorLogLengthCommClient(String username, String password) {
            super(username, password);
            Debug.println(9, "ErrorLogViewer: ErrorLogLengthCommClient.<init>");
        }

        public synchronized void finish() {
            super.finish();
            _logLengthAvailable = true;
            _logLengthCalculating = false;
            ErrorLogViewerModel.this.tableDataChanged();
            Debug.println(9, "ErrorLogViewer: ErrorLogLengthCommClient.finish()");
        }
    }
}


