/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package flex.management.runtime.messaging.services.messaging;

import flex.management.BaseControl;
import flex.management.runtime.AdminConsoleTypes;
import flex.messaging.services.messaging.ThrottleManager;

import java.util.Date;

/**
 * The <code>ThrottleManagerControl</code> class is the MBean implementation for
 * monitoring and managing a <code>ThrottleManager</code> at runtime.
 */
public class ThrottleManagerControl extends BaseControl implements
        ThrottleManagerControlMBean {
    private ThrottleManager throttleManager;
    private long clientIncomingMessageThrottleStart;
    private int clientIncomingMessageThrottleCount;
    private Date lastClientIncomingMessageThrottleTimestamp;
    private long clientOutgoingMessageThrottleStart;
    private int clientOutgoingMessageThrottleCount;
    private Date lastClientOutgoingMessageThrottleTimestamp;
    private long destinationIncomingMessageThrottleStart;
    private int destinationIncomingMessageThrottleCount;
    private Date lastDestinationIncomingMessageThrottleTimestamp;
    private long destinationOutgoingMessageThrottleStart;
    private int destinationOutgoingMessageThrottleCount;
    private Date lastDestinationOutgoingMessageThrottleTimestamp;

    /**
     * Constructs a new <code>ThrottleManagerControl</code> instance, assigning its
     * backing <code>ThrottleManager</code>.
     *
     * @param throttleManager The <code>ThrottleManager</code> managed by this MBean.
     * @param parent          The parent MBean in the management hierarchy.
     */
    public ThrottleManagerControl(ThrottleManager throttleManager, BaseControl parent) {
        super(parent);
        this.throttleManager = throttleManager;
        clientIncomingMessageThrottleStart = System.currentTimeMillis();
        clientOutgoingMessageThrottleStart = clientIncomingMessageThrottleStart;
        destinationIncomingMessageThrottleStart = clientIncomingMessageThrottleStart;
        destinationOutgoingMessageThrottleStart = clientIncomingMessageThrottleStart;
    }

    @Override
    protected void onRegistrationComplete() {
        String name = this.getObjectName().getCanonicalName();
        String[] attributes = {
                "ClientIncomingMessageThrottleCount", "ClientIncomingMessageThrottleFrequency",
                "ClientOutgoingMessageThrottleCount", "ClientOutgoingMessageThrottleFrequency",
                "DestinationIncomingMessageThrottleCount", "DestinationIncomingMessageThrottleFrequency",
                "DestinationOutgoingMessageThrottleCount", "DestinationOutgoingMessageThrottleFrequency",
                "LastClientIncomingMessageThrottleTimestamp", "LastClientOutgoingMessageThrottleTimestamp",
                "LastDestinationIncomingMessageThrottleTimestamp", "LastDestinationOutgoingMessageThrottleTimestamp"
        };

        getRegistrar().registerObjects(AdminConsoleTypes.DESTINATION_POLLABLE, name, attributes);
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.BaseControlMBean#getId()
     */
    @Override
    public String getId() {
        return throttleManager.getId();
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.BaseControlMBean#getType()
     */
    @Override
    public String getType() {
        return ThrottleManager.TYPE;
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getClientIncomingMessageThrottleCount()
     */
    public Integer getClientIncomingMessageThrottleCount() {
        return Integer.valueOf(clientIncomingMessageThrottleCount);
    }

    /**
     * Increments the count of throttled incoming client messages.
     */
    public void incrementClientIncomingMessageThrottleCount() {
        ++clientIncomingMessageThrottleCount;
        lastClientIncomingMessageThrottleTimestamp = new Date();
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#resetClientIncomingMessageThrottleCount()
     */
    public void resetClientIncomingMessageThrottleCount() {
        clientIncomingMessageThrottleStart = System.currentTimeMillis();
        clientIncomingMessageThrottleCount = 0;
        lastClientIncomingMessageThrottleTimestamp = null;
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getLastClientIncomingMessageThrottleTimestamp()
     */
    public Date getLastClientIncomingMessageThrottleTimestamp() {
        return lastClientIncomingMessageThrottleTimestamp;
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getClientIncomingMessageThrottleFrequency()
     */
    public Double getClientIncomingMessageThrottleFrequency() {
        if (clientIncomingMessageThrottleCount > 0) {
            double runtime = differenceInMinutes(clientIncomingMessageThrottleStart, System.currentTimeMillis());
            return new Double(clientIncomingMessageThrottleCount / runtime);
        }
        return new Double(0);
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getClientOutgoingMessageThrottleCount()
     */
    public Integer getClientOutgoingMessageThrottleCount() {
        return Integer.valueOf(clientOutgoingMessageThrottleCount);
    }

    /**
     * Increments the count of throttled outgoing client messages.
     */
    public void incrementClientOutgoingMessageThrottleCount() {
        ++clientOutgoingMessageThrottleCount;
        lastClientOutgoingMessageThrottleTimestamp = new Date();
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#resetClientOutgoingMessageThrottleCount()
     */
    public void resetClientOutgoingMessageThrottleCount() {
        clientOutgoingMessageThrottleStart = System.currentTimeMillis();
        clientOutgoingMessageThrottleCount = 0;
        lastClientOutgoingMessageThrottleTimestamp = null;
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getLastClientOutgoingMessageThrottleTimestamp()
     */
    public Date getLastClientOutgoingMessageThrottleTimestamp() {
        return lastClientOutgoingMessageThrottleTimestamp;
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getClientOutgoingMessageThrottleFrequency()
     */
    public Double getClientOutgoingMessageThrottleFrequency() {
        if (clientOutgoingMessageThrottleCount > 0) {
            double runtime = differenceInMinutes(clientOutgoingMessageThrottleStart, System.currentTimeMillis());
            return new Double(clientOutgoingMessageThrottleCount / runtime);
        }
        return new Double(0);
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getDestinationIncomingMessageThrottleCount()
     */
    public Integer getDestinationIncomingMessageThrottleCount() {
        return Integer.valueOf(destinationIncomingMessageThrottleCount);
    }

    /**
     * Increments the count of throttled incoming destination messages.
     */
    public void incrementDestinationIncomingMessageThrottleCount() {
        ++destinationIncomingMessageThrottleCount;
        lastDestinationIncomingMessageThrottleTimestamp = new Date();
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#resetDestinationIncomingMessageThrottleCount()
     */
    public void resetDestinationIncomingMessageThrottleCount() {
        destinationIncomingMessageThrottleStart = System.currentTimeMillis();
        destinationIncomingMessageThrottleCount = 0;
        lastDestinationIncomingMessageThrottleTimestamp = null;
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getLastDestinationIncomingMessageThrottleTimestamp()
     */
    public Date getLastDestinationIncomingMessageThrottleTimestamp() {
        return lastDestinationIncomingMessageThrottleTimestamp;
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getDestinationIncomingMessageThrottleFrequency()
     */
    public Double getDestinationIncomingMessageThrottleFrequency() {
        if (destinationIncomingMessageThrottleCount > 0) {
            double runtime = differenceInMinutes(destinationIncomingMessageThrottleStart, System.currentTimeMillis());
            return new Double(destinationIncomingMessageThrottleCount / runtime);
        }
        return new Double(0);
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getDestinationOutgoingMessageThrottleCount()
     */
    public Integer getDestinationOutgoingMessageThrottleCount() {
        return Integer.valueOf(destinationOutgoingMessageThrottleCount);
    }

    /**
     * Increments the count of throttled outgoing destination messages.
     */
    public void incrementDestinationOutgoingMessageThrottleCount() {
        ++destinationOutgoingMessageThrottleCount;
        lastDestinationOutgoingMessageThrottleTimestamp = new Date();
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#resetDestinationOutgoingMessageThrottleCount()
     */
    public void resetDestinationOutgoingMessageThrottleCount() {
        destinationOutgoingMessageThrottleStart = System.currentTimeMillis();
        destinationOutgoingMessageThrottleCount = 0;
        lastDestinationOutgoingMessageThrottleTimestamp = null;
    }

    /*
     *  (non-Javadoc)
     * @see flex.management.runtime.ThrottleManagerControlMBean#getLastDestinationOutgoingMessageThrottleTimestamp()
     */
    public Date getLastDestinationOutgoingMessageThrottleTimestamp() {
        return lastDestinationOutgoingMessageThrottleTimestamp;
    }

    public Double getDestinationOutgoingMessageThrottleFrequency() {
        if (destinationOutgoingMessageThrottleCount > 0) {
            double runtime = differenceInMinutes(destinationOutgoingMessageThrottleStart, System.currentTimeMillis());
            return new Double(destinationOutgoingMessageThrottleCount / runtime);
        }
        return new Double(0);
    }
}
