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

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.log4j.Logger;

import com.cloud.network.schema.interfacevlan.InterfaceVlan;
import com.cloud.network.schema.interfacevlan.Interface;
import com.cloud.network.schema.interfacevlan.Vlan;
import com.cloud.network.schema.portprofile.PortProfile;
import com.cloud.network.schema.portprofile.PortProfile.Activate;
import com.cloud.network.schema.portprofile.PortProfile.Static;
import com.cloud.network.schema.portprofile.PortProfileGlobal;
import com.cloud.network.schema.portprofile.VlanProfile;
import com.cloud.network.schema.portprofile.VlanProfile.Switchport;
import com.cloud.network.schema.portprofile.VlanProfile.Switchport.Mode;
import com.cloud.network.schema.portprofile.VlanProfile.Switchport.Trunk;
import com.cloud.network.schema.portprofile.VlanProfile.Switchport.Trunk.Allowed;
import com.cloud.network.schema.portprofile.VlanProfile.SwitchportBasic;
import com.cloud.network.schema.portprofile.VlanProfile.SwitchportBasic.Basic;
import com.cloud.network.schema.showvcs.Output;

public class BrocadeVcsApi {
    private static final Logger s_logger = Logger.getLogger(BrocadeVcsApi.class);

    private final String _host;
    private final String _adminuser;
    private final String _adminpass;

    protected DefaultHttpClient _client;

    protected HttpRequestBase createMethod(String type, String uri) throws BrocadeVcsApiException {
        String url;
        try {
            url = new URL(Constants.PROTOCOL, _host, Constants.PORT, uri).toString();
        } catch (final MalformedURLException e) {
            s_logger.error("Unable to build Brocade Switch API URL", e);
            throw new BrocadeVcsApiException("Unable to build Brocade Switch API URL", e);
        }

        if ("post".equalsIgnoreCase(type)) {
            return new HttpPost(url);
        } else if ("get".equalsIgnoreCase(type)) {
            return new HttpGet(url);
        } else if ("delete".equalsIgnoreCase(type)) {
            return new HttpDelete(url);
        } else if ("patch".equalsIgnoreCase(type)) {
            return new HttpPatch(url);
        } else {
            throw new BrocadeVcsApiException("Requesting unknown method type");
        }
    }

    public BrocadeVcsApi(String address, String username, String password) {
        _host = address;
        _adminuser = username;
        _adminpass = password;
        _client = new DefaultHttpClient();
        _client.getCredentialsProvider().setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(_adminuser, _adminpass));

    }

    /*
     * Get Operational Status
     */
    public Output getSwitchStatus() throws BrocadeVcsApiException {
        return executeRetreiveStatus(Constants.STATUS_URI);

    }

    /*
     * Creates a new virtual network.
     */
    public boolean createNetwork(int vlanId, long networkId) throws BrocadeVcsApiException {

        if (createInterfaceVlan(vlanId)) {

            final PortProfile portProfile = createPortProfile(vlanId, networkId);

            if (portProfile != null) {
                return activatePortProfile(portProfile);
            }
        }
        return false;
    }

    /*
     * Activates a port-profile.
     */
    private boolean activatePortProfile(PortProfile portProfile) throws BrocadeVcsApiException {
        final PortProfileGlobal portProfileGlobal = new PortProfileGlobal();
        portProfile.setVlanProfile(null);
        final Activate activate = new Activate();
        portProfile.setActivate(activate);
        portProfileGlobal.setPortProfile(portProfile);

        //activate port-profile
        return executeUpdateObject(portProfileGlobal, Constants.URI);
    }

    /*
     *  Creates AMPP port-profile.
     */
    private PortProfile createPortProfile(int vlanId, long networkId) throws BrocadeVcsApiException {

        final PortProfile portProfile = new PortProfile();
        portProfile.setName(Constants.PORT_PROFILE_NAME_PREFIX + networkId);
        if (executeCreateObject(portProfile, Constants.URI)) {
            if (createVlanSubProfile(vlanId, portProfile)) {
                return portProfile;
            }
        }
        return null;
    }

    /*
     * Create vlan sub-profile for port-profile
     */
    private boolean createVlanSubProfile(int vlanId, PortProfile portProfile) throws BrocadeVcsApiException {
        final VlanProfile vlanProfile = new VlanProfile();
        portProfile.setVlanProfile(vlanProfile);
        if (executeUpdateObject(portProfile, Constants.URI)) {
            return configureVlanSubProfile(vlanId, portProfile);
        }
        return false;
    }

    /*
     * Configures vlan sub-profile for port-profile.
     * - configure L2 mode for vlan sub-profile
     * - configure trunk mode for vlan sub-profile
     * - configure allowed VLANs for vlan sub-profile
     */
    private boolean configureVlanSubProfile(int vlanId, PortProfile portProfile) throws BrocadeVcsApiException {
        final SwitchportBasic switchPortBasic = new SwitchportBasic();
        final Basic basic = new Basic();
        switchPortBasic.setBasic(basic);
        portProfile.getVlanProfile().setSwitchportBasic(switchPortBasic);
        // configure L2 mode for vlan sub-profile
        if (executeUpdateObject(portProfile, Constants.URI)) {
            VlanProfile vlanProfile = new VlanProfile();
            Switchport switchPort = new Switchport();
            final Mode mode = new Mode();
            mode.setVlanMode("trunk");
            switchPort.setMode(mode);
            vlanProfile.setSwitchport(switchPort);
            portProfile.setVlanProfile(vlanProfile);

            // configure trunk mode for vlan sub-profile
            if (executeUpdateObject(portProfile, Constants.URI)) {
                vlanProfile = new VlanProfile();
                switchPort = new Switchport();
                final Trunk trunk = new Trunk();
                final Allowed allowed = new Allowed();
                final Allowed.Vlan allowedVlan = new Allowed.Vlan();
                allowedVlan.setAdd(vlanId);
                allowed.setVlan(allowedVlan);
                trunk.setAllowed(allowed);
                switchPort.setTrunk(trunk);
                vlanProfile.setSwitchport(switchPort);
                portProfile.setVlanProfile(vlanProfile);

                //configure allowed VLANs for vlan sub-profile
                return executeUpdateObject(portProfile, Constants.URI);
            }
        }

        return false;

    }

    /*
     * Creates a vlan interface.
     */
    private boolean createInterfaceVlan(int vlanId) throws BrocadeVcsApiException {
        final InterfaceVlan interfaceVlan = new InterfaceVlan();
        final Interface interfaceObj = new Interface();
        final Vlan vlan = new Vlan();
        vlan.setName(vlanId);
        interfaceObj.setVlan(vlan);
        interfaceVlan.setInterface(interfaceObj);

        return executeUpdateObject(interfaceVlan, Constants.URI);

    }

    /*
     * Associates a MAC address to virtual network.
     */
    public boolean associateMacToNetwork(long networkId, String macAddress) throws BrocadeVcsApiException {

        final PortProfileGlobal portProfileGlobal = new PortProfileGlobal();
        final PortProfile portProfile = new PortProfile();
        portProfile.setName(Constants.PORT_PROFILE_NAME_PREFIX + networkId);
        final Static staticObj = new Static();
        staticObj.setMacAddress(macAddress);
        portProfile.setStatic(staticObj);
        portProfileGlobal.setPortProfile(portProfile);

        //associates a mac address to a port-profile
        return executeUpdateObject(portProfileGlobal, Constants.URI);
    }

    /*
     * Disassociates a MAC address from virtual network.
     */
    public boolean disassociateMacFromNetwork(long networkId, String macAddress) throws BrocadeVcsApiException {

        final PortProfileGlobal portProfileGlobal = new PortProfileGlobal();
        final PortProfile portProfile = new PortProfile();
        portProfile.setName(Constants.PORT_PROFILE_NAME_PREFIX + networkId);
        final Static staticObj = new Static();
        staticObj.setOperation("delete");
        staticObj.setMacAddress(macAddress);
        portProfile.setStatic(staticObj);
        portProfileGlobal.setPortProfile(portProfile);

        //associates a mac address to a port-profile
        return executeUpdateObject(portProfileGlobal, Constants.URI);
    }

    /*
     * Deletes a new virtual network.
     */
    public boolean deleteNetwork(int vlanId, long networkId) throws BrocadeVcsApiException {

        if (deactivatePortProfile(networkId)) {

            if (deletePortProfile(networkId)) {
                return deleteInterfaceVlan(vlanId);
            }
        }
        return false;
    }

    /*
     * Deletes a vlan interface.
     */
    private boolean deleteInterfaceVlan(int vlanId) throws BrocadeVcsApiException {
        final InterfaceVlan interfaceVlan = new InterfaceVlan();
        final Interface interfaceObj = new Interface();
        final Vlan vlan = new Vlan();
        vlan.setOperation("delete");
        vlan.setName(vlanId);
        interfaceObj.setVlan(vlan);
        interfaceVlan.setInterface(interfaceObj);

        return executeUpdateObject(interfaceVlan, Constants.URI);

    }

    /*
     * Deactivates a port-profile.
     */
    private boolean deactivatePortProfile(long networkId) throws BrocadeVcsApiException {
        final PortProfileGlobal portProfileGlobal = new PortProfileGlobal();
        final PortProfile portProfile = new PortProfile();
        portProfile.setName(Constants.PORT_PROFILE_NAME_PREFIX + networkId);
        final Activate activate = new Activate();
        activate.setOperation("delete");
        portProfile.setActivate(activate);
        portProfileGlobal.setPortProfile(portProfile);

        //activate port-profile
        return executeUpdateObject(portProfileGlobal, Constants.URI);
    }

    /*
     *  Deletes AMPP port-profile.
     */
    private boolean deletePortProfile(long networkId) throws BrocadeVcsApiException {

        final PortProfile portProfile = new PortProfile();
        portProfile.setName(Constants.PORT_PROFILE_NAME_PREFIX + networkId);
        portProfile.setOperation("delete");
        //deletes port-profile
        return executeUpdateObject(portProfile, Constants.URI);
    }

    protected <T> boolean executeUpdateObject(T newObject, String uri) throws BrocadeVcsApiException {

        final boolean result = true;

        if (_host == null || _host.isEmpty() || _adminuser == null || _adminuser.isEmpty() || _adminpass == null || _adminpass.isEmpty()) {
            throw new BrocadeVcsApiException("Hostname/credentials are null or empty");
        }

        final HttpPatch pm = (HttpPatch)createMethod("patch", uri);
        pm.setHeader("Accept", "application/vnd.configuration.resource+xml");

        pm.setEntity(new StringEntity(convertToString(newObject), ContentType.APPLICATION_XML));

        final HttpResponse response = executeMethod(pm);

        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_NO_CONTENT) {

            String errorMessage;
            try {
                errorMessage = responseToErrorMessage(response);
            } catch (final IOException e) {
                s_logger.error("Failed to update object : " + e.getMessage());
                throw new BrocadeVcsApiException("Failed to update object : " + e.getMessage());
            }

            pm.releaseConnection();
            s_logger.error("Failed to update object : " + errorMessage);
            throw new BrocadeVcsApiException("Failed to update object : " + errorMessage);
        }

        pm.releaseConnection();

        return result;
    }

    protected <T> String convertToString(T object) throws BrocadeVcsApiException {

        final StringWriter stringWriter = new StringWriter();

        try {
            final JAXBContext context = JAXBContext.newInstance(object.getClass());
            final Marshaller marshaller = context.createMarshaller();

            marshaller.marshal(object, stringWriter);

        } catch (final JAXBException e) {
            s_logger.error("Failed to convert object to string : " + e.getMessage());
            throw new BrocadeVcsApiException("Failed to convert object to string : " + e.getMessage());
        }

        final String str = stringWriter.toString();
        s_logger.info(str);

        return str;

    }

    protected Output convertToXML(String object) throws BrocadeVcsApiException {

        Output output = null;
        try {
            final JAXBContext context = JAXBContext.newInstance(Output.class);

            final StringReader reader = new StringReader(object);

            final Unmarshaller unmarshaller = context.createUnmarshaller();
            final Object result = unmarshaller.unmarshal(reader);

            if (result instanceof Output) {
                output = (Output)result;
                s_logger.info(output);
            }

        } catch (final JAXBException e) {
            s_logger.error("Failed to convert string to object : " + e.getMessage());
            throw new BrocadeVcsApiException("Failed to convert string to object : " + e.getMessage());
        }

        return output;

    }

    protected <T> boolean executeCreateObject(T newObject, String uri) throws BrocadeVcsApiException {
        if (_host == null || _host.isEmpty() || _adminuser == null || _adminuser.isEmpty() || _adminpass == null || _adminpass.isEmpty()) {
            throw new BrocadeVcsApiException("Hostname/credentials are null or empty");
        }

        final boolean result = true;
        final HttpPost pm = (HttpPost)createMethod("post", uri);
        pm.setHeader("Accept", "application/vnd.configuration.resource+xml");
        pm.setEntity(new StringEntity(convertToString(newObject), ContentType.APPLICATION_XML));

        final HttpResponse response = executeMethod(pm);

        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_CREATED) {

            String errorMessage;
            try {
                errorMessage = responseToErrorMessage(response);
            } catch (final IOException e) {
                s_logger.error("Failed to create object : " + e.getMessage());
                throw new BrocadeVcsApiException("Failed to create object : " + e.getMessage());
            }

            pm.releaseConnection();
            s_logger.error("Failed to create object : " + errorMessage);
            throw new BrocadeVcsApiException("Failed to create object : " + errorMessage);
        }

        pm.releaseConnection();

        return result;
    }

    protected Output executeRetreiveStatus(String uri) throws BrocadeVcsApiException {
        if (_host == null || _host.isEmpty() || _adminuser == null || _adminuser.isEmpty() || _adminpass == null || _adminpass.isEmpty()) {
            throw new BrocadeVcsApiException("Hostname/credentials are null or empty");
        }

        String readLine = null;
        StringBuffer sb = null;

        final HttpPost pm = (HttpPost)createMethod("post", uri);
        pm.setHeader("Accept", "application/vnd.operational-state.resource+xml");
        pm.setEntity(new StringEntity("<show-vcs></show-vcs>", ContentType.APPLICATION_XML));

        final HttpResponse response = executeMethod(pm);

        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {

            String errorMessage;
            try {
                errorMessage = responseToErrorMessage(response);
            } catch (final IOException e) {
                s_logger.error("Failed to retreive status : " + e.getMessage());
                throw new BrocadeVcsApiException("Failed to retreive status : " + e.getMessage());
            }

            pm.releaseConnection();
            s_logger.error("Failed to retreive status : " + errorMessage);
            throw new BrocadeVcsApiException("Failed to retreive status : " + errorMessage);
        }

        try (BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("UTF-8")))) {
            sb = new StringBuffer();

            while ((readLine = br.readLine()) != null) {
                s_logger.debug(readLine);
                sb.append(readLine);

            }
        } catch (final Exception e) {
            s_logger.error("Failed to retreive status : " + e.getMessage());
            throw new BrocadeVcsApiException("Failed to retreive status : " + e.getMessage());
        }

        pm.releaseConnection();

        return convertToXML(sb.toString());
    }

    protected void executeDeleteObject(String uri) throws BrocadeVcsApiException {
        if (_host == null || _host.isEmpty() || _adminuser == null || _adminuser.isEmpty() || _adminpass == null || _adminpass.isEmpty()) {
            throw new BrocadeVcsApiException("Hostname/credentials are null or empty");
        }

        final HttpDelete dm = (HttpDelete)createMethod("delete", uri);
        dm.setHeader("Accept", "application/vnd.configuration.resource+xml");

        final HttpResponse response = executeMethod(dm);

        if (response.getStatusLine().getStatusCode() != HttpStatus.SC_NO_CONTENT) {

            String errorMessage;
            try {
                errorMessage = responseToErrorMessage(response);
            } catch (final IOException e) {
                s_logger.error("Failed to delete object : " + e.getMessage());
                throw new BrocadeVcsApiException("Failed to delete object : " + e.getMessage());
            }

            dm.releaseConnection();
            s_logger.error("Failed to delete object : " + errorMessage);
            throw new BrocadeVcsApiException("Failed to delete object : " + errorMessage);
        }
        dm.releaseConnection();
    }

    protected HttpResponse executeMethod(HttpRequestBase method) throws BrocadeVcsApiException {
        HttpResponse response = null;
        try {
            response = _client.execute(method);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {
                method.releaseConnection();
                response = _client.execute(method);
            }
        } catch (final IOException e) {
            s_logger.error("IOException caught while trying to connect to the Brocade Switch", e);
            method.releaseConnection();
            throw new BrocadeVcsApiException("API call to Brocade Switch Failed", e);
        }

        return response;
    }

    private String responseToErrorMessage(HttpResponse response) throws IOException {

        if ("text/html".equals(response.getEntity().getContentType().getValue())) {

            try (BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), Charset.forName("UTF-8")))) {

                final StringBuffer result = new StringBuffer();
                String line = "";
                while ((line = rd.readLine()) != null) {
                    result.append(line);
                }
                return result.toString();
            }
        }
        return null;
    }

}
