/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the License).  You may not use this file except in
 * compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * Header Notice in each file and include the License file 
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.  
 * If applicable, add the following below the CDDL Header, 
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information: 
 * "Portions Copyrighted [year] [name of copyright owner]"
 * 
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 */

package com.sun.enterprise.tools.admingui.handlers;

import java.util.ArrayList;
import java.util.EventObject;
import java.util.Iterator;
import java.util.Calendar;
import java.util.Date;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import java.util.Random;
import java.text.DateFormat;
import java.util.logging.Level;
import java.lang.Integer;

import com.iplanet.jato.view.View;
import com.iplanet.jato.view.ViewBase;
import com.iplanet.jato.view.ViewBean;
import com.iplanet.jato.RequestContext;
import com.iplanet.jato.RequestManager;
import com.iplanet.jato.model.DefaultModel;
import com.iplanet.jato.model.Model;
import com.iplanet.jato.model.ModelControlException;

import javax.management.MBeanException;
import javax.management.ObjectName;
import javax.management.AttributeList;
import javax.management.Attribute;

import com.sun.enterprise.tools.admingui.util.Util;

import com.sun.enterprise.tools.guiframework.exception.FrameworkException;
import com.sun.enterprise.tools.guiframework.model.ModelManager;
import com.sun.enterprise.tools.guiframework.view.DescriptorCCPageTitle;
import com.sun.enterprise.tools.guiframework.view.DescriptorContainerView;
import com.sun.enterprise.tools.guiframework.view.HandlerContext;
import com.sun.enterprise.tools.guiframework.view.descriptors.ViewDescriptor;
import com.sun.enterprise.tools.guiframework.view.descriptors.CCActionTableDescriptor;
import com.sun.enterprise.tools.guiframework.view.event.BeforeCreateEvent;

import com.sun.web.ui.model.CCActionTableModelInterface;
import com.sun.enterprise.tools.admingui.util.MBeanUtil;
import com.sun.enterprise.tools.admingui.util.AMXUtil;

//need for constants
import com.sun.appserv.management.monitor.ServerRootMonitor;
import com.sun.appserv.management.ext.logging.LogAnalyzer;


public class LogAnalyzerHandler {
    
    private static final String DEMO_INSTANCE_NAME="@demo@";
    private CCActionTableModelInterface getModel(HandlerContext handlerCtx, ViewDescriptor desc) {
        
        CCActionTableModelInterface model =
            (CCActionTableModelInterface)handlerCtx.getInputValue("model");
        if (model == null) {
            throw new FrameworkException("LogAnalyzerHandler.getModel: No Model Specified.",
                desc, handlerCtx.getView());
        }
        
        return model;
    }
    

    private void populateTable(RequestContext ctx, CCActionTableModelInterface model, Map[] attrsMap, Date selectedTimeStamp) 
        throws ModelControlException {
        //System.out.println("!!!!! populateTable !!!");
        model.beforeFirst();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, ctx.getRequest().getLocale());
          
        for(int rowNo=0; rowNo < attrsMap.length; rowNo++){
            model.appendRow();
            Map attrs = attrsMap[rowNo];
            
            Long ms = (Long) attrs.get(LogAnalyzer.TIMESTAMP_KEY);
            model.setValue("timeStamp", ms);
            String formattedTime = dateFormat.format(new Date(ms.longValue()));
            model.setValue("timeStampFormatted", formattedTime);
            
            Integer severe = (Integer) attrs.get(LogAnalyzer.SEVERE_COUNT_KEY);
            Object obj = severe;
            if (severe.intValue() < 0){
                obj = Util.getMessage("common.NA");
            }
            model.setValue("severeCount", obj);

            Integer warning = (Integer) attrs.get(LogAnalyzer.WARNING_COUNT_KEY);
            obj = warning;
            if (warning.intValue() < 0){
                obj = Util.getMessage("common.NA");
            }
            model.setValue("warningCount", obj);

        }
    }
    
    private void printout(CCActionTableModelInterface model)
    {
        Object timeS = model.getValue("timeStamp");
        String timeSClassName= timeS.getClass().getName();
        String tformat = (String) model.getValue("timeStampFormatted");
        Integer sc = (Integer) model.getValue("severeCount");
        Integer wc = (Integer) model.getValue("warningCount");
        //System.out.println("timeSClassName=" + timeSClassName + " timeS="+timeS + " tformat="+tformat + " sc="+sc + " wc="+wc );
    }
  
    public void loadLogAnalyzerTable(RequestContext ctx, HandlerContext handlerCtx) {
        //System.out.println("!!!!! loadLogAnalyzerTable !!!");
	View view = handlerCtx.getView();
        ViewDescriptor desc = null;
        if (handlerCtx.getEvent() instanceof BeforeCreateEvent) {
            desc = ((BeforeCreateEvent)handlerCtx.getEvent()).getViewDescriptor();
	} else {
            DescriptorContainerView descView = (DescriptorContainerView)
                (((ViewBase)view).getParentViewBean());
            desc = descView.getViewDescriptor();
        }

        Map[] attrsMap = (Map[])handlerCtx.getInputValue("statisticsMap");
        if (attrsMap == null || attrsMap.length == 0){
            return;
        }
        Date selectedTimeStamp = (Date) handlerCtx.getInputValue("selectedTimeStamp");
        try {
            CCActionTableModelInterface model = getModel(handlerCtx, desc);
            ((DefaultModel)model).clear();
            model.setRowSelectionType("single");
            populateTable(ctx, model, attrsMap, selectedTimeStamp);
        } catch (Exception ex) {
            throw new FrameworkException("loadAnalyzerTable: Loading error. ", ex, desc, view);
        }
    }
    
    static Map[] map68 = null;
    static Map[] map10 = null;
    
    public void getStatisticsMap(RequestContext ctx, HandlerContext handlerCtx) {
        //System.out.println("!!!!! getStatisticsMap !!!");
        String objectName = (String)handlerCtx.getInputValue("objectName");
        try{
            ObjectName currentObjName = new ObjectName(objectName);
            String serverName = currentObjName.getKeyProperty("server");
            int count = (DEMO_INSTANCE_NAME.equals(serverName)) ? 68 : 5;
            if (count == 68){
                if(map68 == null)
                    map68 = getMap(count);
                handlerCtx.setOutputValue("output", map68);
            }
            else
            if (count == 5){
                if(map10 == null)
                    map10 = getMap(count);
                handlerCtx.setOutputValue("output", map10);
            }    
        }catch (Exception ex){
            ;
        }
    }
    
    private Map[] getMap(int count){
        HashMap[] aMap = new HashMap[count];
        Calendar rightNow = Calendar.getInstance();
        rightNow.add(Calendar.HOUR, -count);
        Random random = new Random();
        for(int i=0; i<count; i++){
            rightNow.add(Calendar.HOUR, 1);
            long tt = rightNow.getTimeInMillis();
            Long tLong = new Long(tt);
            String tkey = LogAnalyzer.TIMESTAMP_KEY;
            String wKey = LogAnalyzer.WARNING_COUNT_KEY;
            String sKey = LogAnalyzer.SEVERE_COUNT_KEY;
           
            HashMap hm = new HashMap();
            hm.put(tkey, tLong);
            
            int xx = Math.abs(random.nextInt()%30);
            Integer xInt = new Integer(xx);
            hm.put(wKey, xInt);
            
            int yy = Math.abs(random.nextInt()%30);
            Integer yInt = new Integer(yy);
            hm.put(sKey, yInt);
            aMap[i] = hm;
        }
        return aMap;
    }
    
    
    public void revertArrayMap(RequestContext ctx, HandlerContext handlerCtx) {
        Map[] inMap = (Map[])handlerCtx.getInputValue("inMap");
        HashMap[] outMap = new HashMap[0];
        
        if(inMap != null && inMap.length > 0){
            outMap = new HashMap[inMap.length];
            for(int i=0,  oix=inMap.length-1; i<inMap.length; i++, oix--){
                outMap[oix] = (HashMap) inMap[i];
            }
        }
        handlerCtx.setOutputValue("outMap", outMap);

    }
    
    public void convertToTimeStampArray(RequestContext ctx, HandlerContext handlerCtx) {
        
        Map[] attrsMap = (Map[])handlerCtx.getInputValue("inputMap");
        View view = handlerCtx.getView();
        DescriptorContainerView descView = (DescriptorContainerView)(((ViewBase)view).getParentViewBean());
        ViewDescriptor desc = descView.getViewDescriptor();
        if (attrsMap == null) {
            throw new FrameworkException("LogAnalyzerHandler.convertToTimeStampArray: No attrsMap specified.",
                desc, handlerCtx.getView());
        }
        ArrayList timeStampArray = new ArrayList();
        for (int rowNo = 0; rowNo < attrsMap.length; rowNo++) {
            Map attrs = attrsMap[rowNo];
            Long ms = (Long) attrs.get(LogAnalyzer.TIMESTAMP_KEY);
            timeStampArray.add(ms.toString());
        }
        handlerCtx.setOutputValue("output", timeStampArray);
    }
    

    public void getSelectedTimeStamp(RequestContext ctx, HandlerContext handlerCtx) {
        //System.out.println("!!!!! getSelectedTimeStamp !!!");
        View view = handlerCtx.getView();
        DescriptorContainerView descView = (DescriptorContainerView)(((ViewBase)view).getParentViewBean());
        ViewDescriptor desc = descView.getViewDescriptor();
        CCActionTableModelInterface model =
            (CCActionTableModelInterface)handlerCtx.getInputValue("model");
        if (model == null) {
            throw new FrameworkException("LogAnalyzerHandler.getSelectedTimeStamp: No Model Specified.",
                desc, handlerCtx.getView());
        }
        
        model.setRowSelectionType("single");
        try{
            model.beforeFirst();
            Object timeStamp = null;
            Object fromKey = null;
            while(model.next()) {
                if (model.isRowSelected()) {
                    int index = model.getRowIndex();
                    timeStamp = model.getValue("timeStamp");
                    String classname = timeStamp.getClass().getName();
                    //System.out.println( "from model, classname=" + classname);
                }
            }
            if (timeStamp == null){
                //System.out.println("+++  in getSelectedTimeStamp: No timeStamp selected ");
            }
            handlerCtx.setOutputValue("selected", timeStamp);
            
        }catch(Exception ex) {
	    throw new FrameworkException("Unable to get Selected TimeStamp:", null, handlerCtx.getView());
	}
    }
    
   
     public void setupChart(RequestContext ctx, HandlerContext handlerCtx) {
        
        View view = handlerCtx.getView();
        DescriptorContainerView descView = (DescriptorContainerView)(((ViewBase)view).getParentViewBean());
        ViewDescriptor desc = descView.getViewDescriptor();
        
        Map[] data = (Map[])handlerCtx.getInputValue("statisticsMap");
        ArrayList timeStampArray = (ArrayList)handlerCtx.getInputValue("timeStampArray");
        if (data == null ) {
                throw new FrameworkException("LogAnalyzerHandler.setupChart: No statisticsMap specified", desc, handlerCtx.getView());
            }
        if (timeStampArray == null ) {
                throw new FrameworkException("LogAnalyzerHandler.setupChart: No timeStampArray specified", desc, handlerCtx.getView());
            }
        
        
        
        String selectedTime = (String)handlerCtx.getInputValue("selectedTime");
        boolean showPrevious10 = Boolean.parseBoolean((String)handlerCtx.getInputValue("showPrevious10"));
        boolean showNext10 = Boolean.parseBoolean((String)handlerCtx.getInputValue("showNext10"));
        boolean useStartEnd = Boolean.parseBoolean((String)handlerCtx.getInputValue("useStartEnd"));
        boolean showAll = Boolean.parseBoolean((String)handlerCtx.getInputValue("showAll"));
        String startT = (String)handlerCtx.getInputValue("start");
        String endT = (String)handlerCtx.getInputValue("end");
        int selected = 0;
        
        boolean showPartial = false;
        
        if ( (selectedTime != null) || showPrevious10 || showNext10 || useStartEnd)
            showPartial=true;
    
        if (!showPartial || showAll){
             handlerCtx.setOutputValue("disableNext10", new Boolean("true"));
             handlerCtx.setOutputValue("disablePrevious10", new Boolean("true"));
             handlerCtx.setOutputValue("disableShowAll", "true");
             handlerCtx.setOutputValue("output", data);
             if (timeStampArray.size() < 11)
                handlerCtx.setOutputValue("disableZoomIn", "true");
             else
                handlerCtx.setOutputValue("disableZoomIn", "false");
             handlerCtx.setOutputValue("startTime", (String)timeStampArray.get(0));
             handlerCtx.setOutputValue("endTime", (String)timeStampArray.get(timeStampArray.size()-1));
             return;
        }
        
        int start =0;
        int end = timeStampArray.size()-1;
        
        if (useStartEnd && !showPrevious10 && !showNext10){
            for(int i=0; i< timeStampArray.size(); i++){
                 if ( ((String)timeStampArray.get(i)).equals( startT)){
                     start = i;
                     break;
                 }
             }
            for(int i=0; i< timeStampArray.size(); i++){
                 if ( ((String)timeStampArray.get(i)).equals( endT)){
                     end = i;
                     break;
                 }
             }
            
        }else{
             if(showPrevious10){
                 selectedTime = (String)handlerCtx.getInputValue("start");
                 if (selectedTime == null) {
                    throw new FrameworkException("LogAnalyzerHandler.setupChart: No start specified with showPrevious", desc, handlerCtx.getView());
                }
             }else
             if (showNext10){
                 selectedTime = (String)handlerCtx.getInputValue("end");
                 if (selectedTime == null) {
                    throw new FrameworkException("LogAnalyzerHandler.setupChart: No end specified with showNext10", desc, handlerCtx.getView());
                 }
             }
                 
             for(int i=0; i< timeStampArray.size(); i++){
                 if ( ((String)timeStampArray.get(i)).equals( selectedTime)){
                     selected = i;
                     break;
                 }
             }
             
             if (showPrevious10){
                 if ( (selected-10) <= 0){
                     start = 0;
                     end = 9;
                 }else{
                     start = selected - 10;
                     end = start + 9;
                 }
             }else
             if (showNext10){
                 start = selected + 1;
                 if ( (start+9 ) >= end){
                 }else{
                     end = start+9;
                 }
             }
             else
             {
                 //the size should always be > 10 when gets to here.
                 if ( (selected-5)>0 && ((selected+4)< timeStampArray.size()-1)){
                    start = selected-5;
                    end = selected+4;
                 }else
                 if ( (selected-5)<= 0){
                     end = start +9;
                 }else{
                     start = end-9;
                 }
              }
            }
             
             int s = start;
             Map[] chartMap = new Map[end-start+1];
             for(int i=0; i<chartMap.length; i++){
                 chartMap[i] = data[s++];
             }
             
             
             handlerCtx.setOutputValue("disablePrevious10", new Boolean((start!=0) ? "false" : "true"));
             handlerCtx.setOutputValue("disableNext10", new Boolean( (end < timeStampArray.size()-1) ? "false" : "true"));
             handlerCtx.setOutputValue("output", chartMap);
             handlerCtx.setOutputValue("startTime", (String)timeStampArray.get(start));
             handlerCtx.setOutputValue("endTime", (String)timeStampArray.get(end));
             handlerCtx.setOutputValue("useStartEnd", "true");
             
             handlerCtx.setOutputValue("disableZoomIn", (timeStampArray.size()<11) ? "true" : "false");
             if(chartMap.length < timeStampArray.size())
                 handlerCtx.setOutputValue("disableShowAll", "false");
             else
                 handlerCtx.setOutputValue("disableShowAll", "true");
     }
     
      public void getFormatedTime(RequestContext ctx, HandlerContext handlerCtx) {
          String ms = (String )handlerCtx.getInputValue("ms");
          Date useThis = null;
          if (ms == null || "".equals(ms)){
            useThis = new Date(System.currentTimeMillis());
          }else{
              useThis = new Date( Long.parseLong(ms));
          }
          DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, ctx.getRequest().getLocale());
          String currentTime = dateFormat.format(useThis);
          handlerCtx.setOutputValue("value", currentTime);
       }

      public void setupDistribution(RequestContext ctx, HandlerContext handlerCtx) {
        
        View view = handlerCtx.getView();
        DescriptorContainerView descView = (DescriptorContainerView)(((ViewBase)view).getParentViewBean());
        ViewDescriptor desc = descView.getViewDescriptor();
        
        Long selectedTime = new Long ((String )handlerCtx.getInputValue("selectedTime"));
        String level = "SEVERE";
        
        if (selectedTime == null ) {
            throw new FrameworkException("LogAnalyzerHandler.setupDistribution: No selectedTime specified", desc, handlerCtx.getView());
        }
        String serverName=(String)handlerCtx.getInputValue("instanceName") ;
        
        Map warningMap = null;
        Map severeMap = null;
        if (serverName.equals(DEMO_INSTANCE_NAME)){
            warningMap = getDistributionSampleData(""+Level.WARNING);
            severeMap = getDistributionSampleData(""+Level.SEVERE);
        }else {
            Map amp = (Map) AMXUtil.getMonitoringRoot().getServerRootMonitorMap();
            ServerRootMonitor srm = (ServerRootMonitor) amp.get(serverName);
            LogAnalyzer la = (LogAnalyzer) srm.getLogging();
            warningMap = la.getErrorDistribution(selectedTime.longValue(), ""+Level.WARNING);
            severeMap = la.getErrorDistribution(selectedTime.longValue(), ""+Level.SEVERE);
        }
        
        
        HashMap combinedMap = new HashMap();
        // combine date from both map
        Iterator iter = severeMap.keySet().iterator();
        while (iter.hasNext()){
            Object key = iter.next();
            Integer value = (Integer) severeMap.get(key);
            Integer counts[]={value, null};
            combinedMap.put(key, counts);
        }
        
        iter = warningMap.keySet().iterator();
        while (iter.hasNext()){
            Object key = iter.next();
            Integer value = (Integer) warningMap.get(key);
            Integer[] counts = (Integer[]) combinedMap.get(key);
            if (counts == null){
                Integer[] vv = {null, value};
                combinedMap.put(key, vv);
            }else{
                counts[1]=value;
            }
        }
        handlerCtx.setOutputValue("combinedMap", combinedMap);
      }
      
      private Map getDistributionSampleData(String level){
          Map dMap = new HashMap();
          Random random = new Random();
          if (level.equals("SEVERE")){
              dMap.put("javax.enterprise.system.container.web", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.resource.corba.S1AS-ORB.rpc.transport", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.system.core.transaction", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.system.tools.admin", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.system.container.ejb", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("org.apache.catalina.startup.ContextConfig", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.system.core", new Integer(Math.abs(random.nextInt()%100)));
              
          }else
          {
              dMap.put("org.apache.catalina.core.StandardEngine", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.system.container.web", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.resource.corba.S1AS-ORB.rpc.transport", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.system.core.transaction", new Integer(Math.abs(random.nextInt()%100)));
              dMap.put("javax.enterprise.system.tools.admin", new Integer(Math.abs(random.nextInt()%100)));
          }
          return dMap;
      }

      public void loadDistributionTable(RequestContext ctx, HandlerContext handlerCtx) {
	View view = handlerCtx.getView();
        ViewDescriptor desc = null;
        if (handlerCtx.getEvent() instanceof BeforeCreateEvent) {
            desc = ((BeforeCreateEvent)handlerCtx.getEvent()).getViewDescriptor();
	} else {
            DescriptorContainerView descView = (DescriptorContainerView)
                (((ViewBase)view).getParentViewBean());
            desc = descView.getViewDescriptor();
        }

        Map combinedMap = (Map)handlerCtx.getInputValue("combinedMap");
        try {
            CCActionTableModelInterface model = getModel(handlerCtx, desc);
            ((DefaultModel)model).clear();
            model.beforeFirst();
            Iterator iters = combinedMap.keySet().iterator();
            while (iters.hasNext()){
                model.appendRow();
                Object key = iters.next();
                Integer[] value = (Integer[]) combinedMap.get(key);
                model.setValue("moduleId", key);
                if (value[0] != null)
                    model.setValue("severeCount", value[0]);
                if (value[1] != null)
                    model.setValue("warningCount", value[1]);
            }
        } catch (Exception ex) {
            throw new FrameworkException("loadAnalyzerTable: Loading error. ", ex, desc, view);
        }
    }
      
}
