// 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 com.cloud.network.security;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.management.StandardMBean;

import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.security.LocalSecurityGroupWorkQueue.LocalSecurityGroupWork;
import com.cloud.network.security.SecurityGroupWork.Step;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine.Type;
import com.cloud.network.security.SecurityRule.SecurityRuleType;

public class SecurityManagerMBeanImpl extends StandardMBean implements SecurityGroupManagerMBean, RuleUpdateLog {
    SecurityGroupManagerImpl2 _sgMgr;
    boolean _monitoringEnabled = false;
    //keep track of last scheduled, last update sent and last seqno sent per vm. Make it available over JMX
    Map<Long, Date> _scheduleTimestamps = new ConcurrentHashMap<Long, Date>(4000, 100, 64);
    Map<Long, Date> _updateTimestamps = new ConcurrentHashMap<Long, Date>(4000, 100, 64);
    
    
    protected SecurityManagerMBeanImpl(SecurityGroupManagerImpl2 securityGroupManager) {
        super(SecurityGroupManagerMBean.class, false);
        this._sgMgr = securityGroupManager;
    }




    @Override
    public int getQueueSize() {
       return this._sgMgr.getQueueSize();
    }
    
    @Override
    public void logUpdateDetails(Long vmId, Long seqno) {
        if (_monitoringEnabled) {
            _updateTimestamps.put(vmId, new Date());
        }
       
    }
    
    @Override
    public void logScheduledDetails(Set<Long> vmIds) {
        if (_monitoringEnabled) {
            for (Long vmId : vmIds) {
                _scheduleTimestamps.put(vmId, new Date());
            }
        }
    }
    
    @Override
    public void enableUpdateMonitor(boolean enable) {
        _monitoringEnabled = enable;
        if (!enable) {
            _updateTimestamps.clear();
            _scheduleTimestamps.clear();
        }
    }


    @Override
    public Map<Long, Date> getScheduledTimestamps() {
        return _scheduleTimestamps;
    }

    @Override
    public Map<Long, Date> getLastUpdateSentTimestamps() {
        return _updateTimestamps;
    }


    @Override
    public List<Long> getVmsInQueue() {
        return _sgMgr.getWorkQueue().getVmsInQueue();
    }




    @Override
    public void disableSchedulerForVm(Long vmId) {
        _sgMgr.disableSchedulerForVm(vmId,  true);
        
    }

    @Override
    public void enableSchedulerForVm(Long vmId) {
        _sgMgr.disableSchedulerForVm(vmId,  false);
        
    }
    
    @Override
    public Long[] getDisabledVmsForScheduler() {
        return _sgMgr.getDisabledVmsForScheduler();
    }


    @Override
    public void enableSchedulerForAllVms() {
        _sgMgr.enableAllVmsForScheduler();
        
    }


    @Override
    public void scheduleRulesetUpdateForVm(Long vmId) {
        List<Long> affectedVms = new ArrayList<Long>(1);
        affectedVms.add(vmId);
        _sgMgr.scheduleRulesetUpdateToHosts(affectedVms, true, null);
    }


    @Override
    public void tryRulesetUpdateForVmBypassSchedulerVeryDangerous(Long vmId, Long seqno) {
       LocalSecurityGroupWork work = new LocalSecurityGroupWorkQueue.LocalSecurityGroupWork(vmId, seqno, Step.Scheduled);
        _sgMgr.sendRulesetUpdates(work);
    }
    
    @Override
    public void simulateVmStart(Long vmId) {
        //all we need is the vmId
        VMInstanceVO vm = new VMInstanceVO(vmId, 5, "foo", "foo", Type.User, null, HypervisorType.Any, 8, 1, 1, false, false,null);
        _sgMgr.handleVmStarted(vm);
    }
    
    @Override
    public void disableSchedulerEntirelyVeryDangerous(boolean disable) {
        _sgMgr.disableScheduler(disable);
    }

    @Override
    public boolean isSchedulerDisabledEntirely() {
       return _sgMgr.isSchedulerDisabled();
    }

    @Override
    public void clearSchedulerQueueVeryDangerous() {
        _sgMgr.clearWorkQueue();
    }
}
