// 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.bridge.service.core.ec2;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.cloud.bridge.service.exception.EC2ServiceException;
import com.cloud.bridge.service.exception.EC2ServiceException.ClientError;

public class EC2KeyPairFilterSet {
    protected final static Logger logger = Logger.getLogger(EC2KeyPairFilterSet.class);

    protected List<EC2Filter> filterSet = new ArrayList<EC2Filter>();

    private Map<String, String> filterTypes = new HashMap<String, String>();

    public EC2KeyPairFilterSet() {
        // -> use these values to check that the proper filter is passed to this type of filter set
        filterTypes.put("fingerprint", "String");
        filterTypes.put("key-name", "String");
    }

    public void addFilter(EC2Filter param) {
        String filterName = param.getName();
        String value = (String)filterTypes.get(filterName);

        if (value == null || value.equalsIgnoreCase("null")) {
            throw new EC2ServiceException(ClientError.InvalidFilter, "Filter '" + filterName + "' is invalid");
        }

        // ToDo we could add checks to make sure the type of a filters value is correct (e.g., an integer)
        filterSet.add(param);
    }

    public EC2Filter[] getFilterSet() {
        return filterSet.toArray(new EC2Filter[0]);
    }

    public EC2DescribeKeyPairsResponse evaluate(EC2DescribeKeyPairsResponse response) throws ParseException {
        EC2DescribeKeyPairsResponse resultList = new EC2DescribeKeyPairsResponse();

        boolean matched;

        EC2SSHKeyPair[] keyPairSet = response.getKeyPairSet();
        EC2Filter[] filterSet = getFilterSet();
        for (EC2SSHKeyPair keyPair : keyPairSet) {
            matched = true;
            for (EC2Filter filter : filterSet) {
                if (!filterMatched(keyPair, filter)) {
                    matched = false;
                    break;
                }
            }
            if (matched == true)
                resultList.addKeyPair(keyPair);

        }
        return resultList;
    }

    private boolean filterMatched(EC2SSHKeyPair keypair, EC2Filter filter) throws ParseException {
        String filterName = filter.getName();
        String[] valueSet = filter.getValueSet();

        if (filterName.equalsIgnoreCase("fingerprint")) {
            return containsString(keypair.getFingerprint(), valueSet);
        } else if (filterName.equalsIgnoreCase("key-name")) {
            return containsString(keypair.getKeyName(), valueSet);
        }
        return false;
    }

    private boolean containsString(String lookingFor, String[] set) {
        if (lookingFor == null)
            return false;

        for (String filter : set) {
            if (lookingFor.matches(filter))
                return true;
        }
        return false;
    }

}
