// 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.rules;

import java.util.List;

import com.cloud.api.commands.ListPortForwardingRulesCmd;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.NetworkRuleConflictException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.user.Account;
import com.cloud.utils.Pair;

public interface RulesService {
    Pair<List<? extends FirewallRule>, Integer> searchStaticNatRules(Long ipId, Long id, Long vmId, Long start, Long size, String accountName, Long domainId, Long projectId, boolean isRecursive, boolean listAll);

    /**
     * Creates a port forwarding rule between two ip addresses or between
     * an ip address and a virtual machine.
     * 
     * @param rule
     *            rule to be created.
     * @param vmId
     *            vm to be linked to. If specified the destination ip address is ignored.
     * @param openFirewall
     *            TODO
     * @return PortForwardingRule if created.
     * @throws NetworkRuleConflictException
     *             if conflicts in the network rules are detected.
     */
    PortForwardingRule createPortForwardingRule(PortForwardingRule rule, Long vmId, boolean openFirewall) throws NetworkRuleConflictException;

    /**
     * Revokes a port forwarding rule
     * 
     * @param ruleId
     *            the id of the rule to revoke.
     * @param caller
     * @return
     */
    boolean revokePortForwardingRule(long ruleId, boolean apply);

    /**
     * List port forwarding rules assigned to an ip address
     * 
     * @param cmd
     *            the command object holding the criteria for listing port forwarding rules (the ipAddress)
     * @return list of port forwarding rules on the given address, empty list if no rules exist
     */
    public Pair<List<? extends PortForwardingRule>, Integer> listPortForwardingRules(ListPortForwardingRulesCmd cmd);

    boolean applyPortForwardingRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;

    boolean enableStaticNat(long ipAddressId, long vmId, long networkId, boolean isSystemVm) throws NetworkRuleConflictException, ResourceUnavailableException;

    PortForwardingRule getPortForwardigRule(long ruleId);

    FirewallRule getFirewallRule(long ruleId);

    StaticNatRule createStaticNatRule(StaticNatRule rule, boolean openFirewall) throws NetworkRuleConflictException;

    boolean revokeStaticNatRule(long ruleId, boolean apply);

    boolean applyStaticNatRules(long ipAdddressId, Account caller) throws ResourceUnavailableException;

    StaticNatRule buildStaticNatRule(FirewallRule rule, boolean forRevoke);

    List<String> getSourceCidrs(long ruleId);

    boolean disableStaticNat(long ipId) throws ResourceUnavailableException, NetworkRuleConflictException, InsufficientAddressCapacityException;

}
