/**
 * 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 org.apache.falcon.client;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties;
import com.sun.jersey.multipart.FormDataMultiPart;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.util.TrustManagerUtils;
import org.apache.falcon.LifeCycle;
import org.apache.falcon.ExtensionHandler;
import org.apache.falcon.entity.v0.DateValidator;
import org.apache.falcon.entity.v0.Entity;
import org.apache.falcon.entity.v0.EntityType;
import org.apache.falcon.extensions.ExtensionType;
import org.apache.falcon.metadata.RelationshipType;
import org.apache.falcon.resource.APIResult;
import org.apache.falcon.resource.EntityList;
import org.apache.falcon.resource.EntitySummaryResult;
import org.apache.falcon.resource.ExtensionInstanceList;
import org.apache.falcon.resource.ExtensionJobList;
import org.apache.falcon.resource.FeedInstanceResult;
import org.apache.falcon.resource.FeedLookupResult;
import org.apache.falcon.resource.InstanceDependencyResult;
import org.apache.falcon.resource.InstancesResult;
import org.apache.falcon.resource.InstancesSummaryResult;
import org.apache.falcon.resource.LineageGraphResult;
import org.apache.falcon.resource.SchedulableEntityInstanceResult;
import org.apache.falcon.resource.TriageResult;
import org.apache.hadoop.security.authentication.client.AuthenticatedURL;
import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;
import org.apache.hadoop.security.authentication.client.PseudoAuthenticator;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.security.SecureRandom;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Client API to submit and manage Falcon Entities (Cluster, Feed, Process) jobs
 * against an Falcon instance.
 */
public class FalconClient extends AbstractFalconClient {

    public static final AtomicReference<PrintStream> OUT = new AtomicReference<>(System.out);

    public static final String WS_HEADER_PREFIX = "header:";
    public static final String USER = System.getProperty("user.name");
    private static final String AUTH_URL = "api/options?" + PseudoAuthenticator.USER_NAME + "=" + USER;

    private static final String PATH = "path";
    private static final String COLO = "colo";
    private static final String KEY = "key";
    private static final String VALUE = "value";
    public static final String CLUSTER = "cluster";
    private static final String RUN_ID = "runid";
    private static final String FORCE = "force";
    private static final String SHOW_SCHEDULER = "showScheduler";
    private static final String ENTITY_NAME = "name";
    private static final String ENTITY_TYPE = "type";
    private static final String SKIP_DRYRUN = "skipDryRun";
    private static final String FILTER_BY = "filterBy";
    private static final String ORDER_BY = "orderBy";
    private static final String SORT_ORDER = "sortOrder";
    private static final String OFFSET = "offset";
    private static final String NUM_RESULTS = "numResults";
    private static final String START = "start";
    private static final String END = "end";
    private static final String INSTANCE_TIME = "instanceTime";
    private static final String INSTANCE_STATUS = "instanceStatus";
    private static final String PROPERTIES = "properties";
    private static final String FIELDS = "fields";
    private static final String NAME_SUBSEQUENCE = "nameseq";
    private static final String FILTER_TAGS = "tags";
    private static final String TAG_KEYWORDS = "tagkeys";
    private static final String LIFECYCLE = "lifecycle";
    private static final String NUM_INSTANCES = "numInstances";
    private static final String ALL_ATTEMPTS = "allAttempts";




    private static final String DO_AS_OPT = "doAs";
    private static final String JOB_NAME_OPT = "jobName";
    public static final String ENTITIES_OPT = "entities";
    /**
     * Name of the HTTP cookie used for the authentication token between the client and the server.
     */
    private static final String AUTH_COOKIE = "hadoop.auth";
    private static final String AUTH_COOKIE_EQ = AUTH_COOKIE + "=";

    private static final KerberosAuthenticator AUTHENTICATOR = new KerberosAuthenticator();
    private static final String TEMPLATE_SUFFIX = "-template.xml";


    private static final String PROPERTIES_SUFFIX = ".properties";
    private static final HostnameVerifier ALL_TRUSTING_HOSTNAME_VERIFIER = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession sslSession) {
            return true;
        }
    };
    private static final String FEEDS = "feeds";
    private static final String PROCESSES = "processes";
    private static final String CONFIG = "config";
    private final WebResource service;
    private final AuthenticatedURL.Token authenticationToken;

    /**
     * debugMode=false means no debugging. debugMode=true means debugging on.
     */
    private boolean debugMode = false;

    private final Properties clientProperties;

    /**
     * Create a Falcon client instance.
     *
     * @param falconUrl of the server to which client interacts
     * @ - If unable to initialize SSL Props
     */
    public FalconClient(String falconUrl) {
        this(falconUrl, new Properties());
    }

    /**
     * Create a Falcon client instance.
     *
     * @param falconUrl of the server to which client interacts
     * @param properties client properties
     * @ - If unable to initialize SSL Props
     */
    public FalconClient(String falconUrl, Properties properties)  {
        try {
            String baseUrl = notEmpty(falconUrl, "FalconUrl");
            if (!baseUrl.endsWith("/")) {
                baseUrl += "/";
            }
            this.clientProperties = properties;
            SSLContext sslContext = getSslContext();
            DefaultClientConfig config = new DefaultClientConfig();
            config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
                    new HTTPSProperties(ALL_TRUSTING_HOSTNAME_VERIFIER, sslContext)
            );
            Client client = Client.create(config);
            client.setConnectTimeout(Integer.parseInt(clientProperties.getProperty("falcon.connect.timeout",
                    "180000")));
            client.setReadTimeout(Integer.parseInt(clientProperties.getProperty("falcon.read.timeout", "180000")));
            service = client.resource(UriBuilder.fromUri(baseUrl).build());
            client.resource(UriBuilder.fromUri(baseUrl).build());
            authenticationToken = getToken(baseUrl);
        } catch (Exception e) {
            throw new FalconCLIException("Unable to initialize Falcon Client object. Cause : " + e.getMessage(), e);
        }
    }

    private static SSLContext getSslContext() throws Exception {
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(
                null,
                new TrustManager[]{TrustManagerUtils.getValidateServerCertificateTrustManager()},
                new SecureRandom());
        return sslContext;
    }

    /**
     * @return current debug Mode
     */
    public boolean getDebugMode() {
        return debugMode;
    }

    /**
     * Set debug mode.
     *
     * @param debugMode : debugMode=false means no debugging. debugMode=true means debugging on
     */
    public void setDebugMode(boolean debugMode) {
        this.debugMode = debugMode;
    }

    public static AuthenticatedURL.Token getToken(String baseUrl)  {
        AuthenticatedURL.Token currentToken = new AuthenticatedURL.Token();
        try {
            URL url = new URL(baseUrl + AUTH_URL);
            // using KerberosAuthenticator which falls back to PsuedoAuthenticator
            // instead of passing authentication type from the command line - bad factory
            HttpsURLConnection.setDefaultSSLSocketFactory(getSslContext().getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(ALL_TRUSTING_HOSTNAME_VERIFIER);
            new AuthenticatedURL(AUTHENTICATOR).openConnection(url, currentToken);
        } catch (Exception ex) {
            throw new FalconCLIException("Could not authenticate, " + ex.getMessage(), ex);
        }

        return currentToken;
    }


    /**
     * Methods allowed on Entity Resources.
     */
    protected static enum Entities {
        VALIDATE("api/entities/validate/", HttpMethod.POST, MediaType.TEXT_XML),
        SUBMIT("api/entities/submit/", HttpMethod.POST, MediaType.TEXT_XML),
        UPDATE("api/entities/update/", HttpMethod.POST, MediaType.TEXT_XML),
        UPDATEDEPENDENTS("api/entities/updateClusterDependents/", HttpMethod.POST, MediaType.TEXT_XML),
        SUBMITANDSCHEDULE("api/entities/submitAndSchedule/", HttpMethod.POST, MediaType.TEXT_XML),
        SCHEDULE("api/entities/schedule/", HttpMethod.POST, MediaType.TEXT_XML),
        SUSPEND("api/entities/suspend/", HttpMethod.POST, MediaType.TEXT_XML),
        RESUME("api/entities/resume/", HttpMethod.POST, MediaType.TEXT_XML),
        DELETE("api/entities/delete/", HttpMethod.DELETE, MediaType.TEXT_XML),
        STATUS("api/entities/status/", HttpMethod.GET, MediaType.TEXT_XML),
        DEFINITION("api/entities/definition/", HttpMethod.GET, MediaType.TEXT_XML),
        LIST("api/entities/list/", HttpMethod.GET, MediaType.TEXT_XML),
        SUMMARY("api/entities/summary", HttpMethod.GET, MediaType.APPLICATION_JSON),
        LOOKUP("api/entities/lookup/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        DEPENDENCY("api/entities/dependencies/", HttpMethod.GET, MediaType.TEXT_XML),
        SLA("api/entities/sla-alert", HttpMethod.GET, MediaType.APPLICATION_JSON),
        TOUCH("api/entities/touch", HttpMethod.POST, MediaType.TEXT_XML);

        private String path;
        private String method;
        private String mimeType;

        Entities(String path, String method, String mimeType) {
            this.path = path;
            this.method = method;
            this.mimeType = mimeType;
        }
    }

    /**
     * Methods allowed on Metadata Discovery Resources.
     */
    protected static enum MetadataOperations {

        LIST("api/metadata/discovery/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        RELATIONS("api/metadata/discovery/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        VERTICES("api/metadata/lineage/vertices", HttpMethod.GET, MediaType.APPLICATION_JSON),
        EDGES("api/metadata/lineage/edges", HttpMethod.GET, MediaType.APPLICATION_JSON),
        LINEAGE("api/metadata/lineage/entities", HttpMethod.GET, MediaType.APPLICATION_JSON);

        private String path;
        private String method;
        private String mimeType;

        MetadataOperations(String path, String method, String mimeType) {
            this.path = path;
            this.method = method;
            this.mimeType = mimeType;
        }
    }

    /**
     * Methods allowed on Process Instance Resources.
     */
    protected static enum Instances {
        RUNNING("api/instance/running/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        STATUS("api/instance/status/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        LIST("api/instance/list", HttpMethod.GET, MediaType.APPLICATION_JSON),
        KILL("api/instance/kill/", HttpMethod.POST, MediaType.APPLICATION_JSON),
        SUSPEND("api/instance/suspend/", HttpMethod.POST, MediaType.APPLICATION_JSON),
        RESUME("api/instance/resume/", HttpMethod.POST, MediaType.APPLICATION_JSON),
        RERUN("api/instance/rerun/", HttpMethod.POST, MediaType.APPLICATION_JSON),
        LOG("api/instance/logs/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        SUMMARY("api/instance/summary/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        PARAMS("api/instance/params/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        DEPENDENCY("api/instance/dependencies/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        TRIAGE("api/instance/triage/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        LISTING("api/instance/listing/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        SEARCH("api/instance/search/", HttpMethod.GET, MediaType.APPLICATION_JSON);

        private String path;
        private String method;
        private String mimeType;

        Instances(String path, String method, String mimeType) {
            this.path = path;
            this.method = method;
            this.mimeType = mimeType;
        }
    }

    protected static enum AdminOperations {

        STACK("api/admin/stack", HttpMethod.GET, MediaType.TEXT_PLAIN),
        VERSION("api/admin/version", HttpMethod.GET, MediaType.APPLICATION_JSON),
        SAFEMODE("api/admin/setSafeMode", HttpMethod.GET, MediaType.APPLICATION_JSON);

        private String path;
        private String method;
        private String mimeType;

        AdminOperations(String path, String method, String mimeType) {
            this.path = path;
            this.method = method;
            this.mimeType = mimeType;
        }
    }

    /**
     * Methods allowed on Extension Resources.
     */
    protected static enum ExtensionOperations {

        ENUMERATE("api/extension/enumerate/", HttpMethod.GET, MediaType.TEXT_XML),
        DESCRIBE("api/extension/describe/", HttpMethod.GET, MediaType.TEXT_PLAIN),
        DEFINITION("api/extension/definition", HttpMethod.GET, MediaType.APPLICATION_JSON),
        LIST("api/extension/list", HttpMethod.GET, MediaType.APPLICATION_JSON),
        INSTANCES("api/extension/instances", HttpMethod.GET, MediaType.APPLICATION_JSON),
        SUBMIT("api/extension/submit", HttpMethod.POST, MediaType.TEXT_XML),
        SUBMIT_AND_SCHEDULE("api/extension/submitAndSchedule", HttpMethod.POST, MediaType.TEXT_XML),
        UPDATE("api/extension/update", HttpMethod.POST, MediaType.TEXT_XML),
        VALIDATE("api/extension/validate", HttpMethod.POST, MediaType.TEXT_XML),
        SCHEDULE("api/extension/schedule", HttpMethod.POST, MediaType.TEXT_XML),
        SUSPEND("api/extension/suspend", HttpMethod.POST, MediaType.TEXT_XML),
        RESUME("api/extension/resume", HttpMethod.POST, MediaType.TEXT_XML),
        DELETE("api/extension/delete", HttpMethod.POST, MediaType.TEXT_XML),
        UNREGISTER("api/extension/unregister/", HttpMethod.POST, MediaType.TEXT_XML),
        DETAIL("api/extension/detail/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        JOB_DETAILS("api/extension/extensionJobDetails/", HttpMethod.GET, MediaType.APPLICATION_JSON),
        REGISTER("api/extension/register/", HttpMethod.POST, MediaType.TEXT_XML),
        ENABLE("api/extension/enable", HttpMethod.POST, MediaType.TEXT_XML),
        DISABLE("api/extension/disable", HttpMethod.POST, MediaType.TEXT_XML);

        private String path;
        private String method;
        private String mimeType;

        ExtensionOperations(String path, String method, String mimeType) {
            this.path = path;
            this.method = method;
            this.mimeType = mimeType;
        }
    }

    private String notEmpty(String str, String name) {
        if (str == null) {
            throw new IllegalArgumentException(name + " cannot be null");
        }
        if (str.length() == 0) {
            throw new IllegalArgumentException(name + " cannot be empty");
        }
        return str;
    }

    public APIResult schedule(EntityType entityType, String entityName, String colo,
                              Boolean skipDryRun, String doAsUser, String properties) {
        String type = entityType.toString().toLowerCase();
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.SCHEDULE.path, type, entityName)
            .addQueryParam(COLO, colo).addQueryParam(SKIP_DRYRUN, skipDryRun)
            .addQueryParam(PROPERTIES, properties).addQueryParam(DO_AS_OPT, doAsUser).call(Entities.SCHEDULE);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult suspend(EntityType entityType, String entityName, String colo, String doAsUser) {
        String type = entityType.toString().toLowerCase();
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.SUSPEND.path, type, entityName)
            .addQueryParam(COLO, colo).addQueryParam(DO_AS_OPT, doAsUser).call(Entities.SUSPEND);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult resume(EntityType entityType, String entityName, String colo, String doAsUser) {
        String type = entityType.toString().toLowerCase();
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.RESUME.path, type, entityName)
            .addQueryParam(COLO, colo).addQueryParam(DO_AS_OPT, doAsUser).call(Entities.RESUME);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult delete(EntityType entityType, String entityName, String doAsUser) {
        String type = entityType.toString().toLowerCase();
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.DELETE.path, type, entityName)
            .addQueryParam(DO_AS_OPT, doAsUser).call(Entities.DELETE);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult validate(String entityType, String filePath, Boolean skipDryRun, String doAsUser) {
        InputStream entityStream = getServletInputStream(filePath);
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.VALIDATE.path, entityType)
            .addQueryParam(SKIP_DRYRUN, skipDryRun).addQueryParam(DO_AS_OPT, doAsUser)
            .call(Entities.VALIDATE, entityStream);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult submit(String entityType, String filePath, String doAsUser) {
        InputStream entityStream = getServletInputStream(filePath);
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.SUBMIT.path, entityType)
            .addQueryParam(DO_AS_OPT, doAsUser).call(Entities.SUBMIT, entityStream);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult update(String entityType, String entityName, String filePath,
                            Boolean skipDryRun, String doAsUser) {
        InputStream entityStream = getServletInputStream(filePath);
        Entities operation = Entities.UPDATE;
        ClientResponse clientResponse = new ResourceBuilder().path(operation.path, entityType, entityName)
            .addQueryParam(SKIP_DRYRUN, skipDryRun).addQueryParam(DO_AS_OPT, doAsUser)
            .call(operation, entityStream);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult updateClusterDependents(String clusterName, Boolean skipDryRun,
                                             String doAsUser)  {
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.UPDATEDEPENDENTS.path, clusterName)
                .addQueryParam(SKIP_DRYRUN, skipDryRun).addQueryParam(DO_AS_OPT, doAsUser)
                .call(Entities.UPDATEDEPENDENTS);
        return getResponse(APIResult.class, clientResponse);
    }

    @Override
    public APIResult submitAndSchedule(String entityType, String filePath, Boolean skipDryRun,
                                       String doAsUser, String properties) {
        InputStream entityStream = getServletInputStream(filePath);
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.SUBMITANDSCHEDULE.path, entityType)
            .addQueryParam(SKIP_DRYRUN, skipDryRun).addQueryParam(DO_AS_OPT, doAsUser)
            .addQueryParam(PROPERTIES, properties).call(Entities.SUBMITANDSCHEDULE, entityStream);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult getStatus(EntityType entityType, String entityName, String colo,
                               String doAsUser, boolean showScheduler) {
        String type = entityType.toString().toLowerCase();
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.STATUS.path, type, entityName)
            .addQueryParam(COLO, colo).addQueryParam(DO_AS_OPT, doAsUser)
            .addQueryParam(SHOW_SCHEDULER, showScheduler).call(Entities.STATUS);

        return getResponse(APIResult.class, clientResponse);
    }

    public Entity getDefinition(String entityType, String entityName, String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.DEFINITION.path, entityType, entityName)
            .call(Entities.DEFINITION);
        String entity = getResponseAsString(clientResponse);
        return Entity.fromString(EntityType.getEnum(entityType), entity);
    }

    public EntityList getDependency(String entityType, String entityName, String doAsUser) {

        ClientResponse clientResponse = new ResourceBuilder().path(Entities.DEPENDENCY.path, entityType, entityName)
            .addQueryParam(DO_AS_OPT, doAsUser).call(Entities.DEPENDENCY);

        printClientResponse(clientResponse);
        checkIfSuccessful(clientResponse);

        EntityList result = clientResponse.getEntity(EntityList.class);
        if (result == null) {
            return new EntityList();
        }
        return result;
    }

    //SUSPEND CHECKSTYLE CHECK ParameterNumberCheck

    public SchedulableEntityInstanceResult getFeedSlaMissPendingAlerts(String entityType, String entityName,
                                           String startTime, String endTime, String colo) {
        ClientResponse clientResponse  = new ResourceBuilder().path(Entities.SLA.path, entityType)
            .addQueryParam(START, startTime).addQueryParam(COLO, colo).addQueryParam(END, endTime)
            .addQueryParam(ENTITY_NAME, entityName).call(Entities.SLA);
        return getResponse(SchedulableEntityInstanceResult.class, clientResponse);
    }

    public TriageResult triage(String entityType, String entityName, String instanceTime,
                               String colo) {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.TRIAGE.path, entityType, entityName)
            .addQueryParam(START, instanceTime).addQueryParam(COLO, colo).call(Instances.TRIAGE);
        return getResponse(TriageResult.class, clientResponse);
    }

    @Override
    public EntityList getEntityList(String entityType, String fields, String nameSubsequence, String tagKeywords,
                                    String filterBy, String filterTags, String orderBy, String sortOrder,
                                    Integer offset, Integer numResults, String doAsUser) {
        Entities operation = Entities.LIST;
        ClientResponse clientResponse = new ResourceBuilder().path(operation.path, entityType)
            .addQueryParam(DO_AS_OPT, doAsUser).addQueryParam(NUM_RESULTS, numResults)
            .addQueryParam(OFFSET, offset).addQueryParam(SORT_ORDER, sortOrder)
            .addQueryParam(ORDER_BY, orderBy).addQueryParam(FILTER_BY, filterBy)
            .addQueryParam(FIELDS, fields).addQueryParam(NAME_SUBSEQUENCE, nameSubsequence)
            .addQueryParam(TAG_KEYWORDS, tagKeywords).addQueryParam(FILTER_TAGS, filterTags)
            .call(operation);

        printClientResponse(clientResponse);
        checkIfSuccessful(clientResponse);

        EntityList result = clientResponse.getEntity(EntityList.class);
        if (result == null || result.getElements() == null) {
            return null;
        }
        return result;
    }

    @Override
    public EntitySummaryResult getEntitySummary(String entityType, String cluster, String start, String end,
                                   String fields, String filterBy, String filterTags,
                                   String orderBy, String sortOrder, Integer offset, Integer numResults,
                                   Integer numInstances, String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(Entities.SUMMARY.path, entityType)
            .addQueryParam(CLUSTER, cluster).addQueryParam(START, start).addQueryParam(END, end)
            .addQueryParam(SORT_ORDER, sortOrder).addQueryParam(ORDER_BY, orderBy)
            .addQueryParam(OFFSET, offset).addQueryParam(NUM_RESULTS, numResults)
            .addQueryParam(DO_AS_OPT, doAsUser).addQueryParam(FILTER_BY, filterBy)
            .addQueryParam(NUM_INSTANCES, numInstances).addQueryParam(FIELDS, fields)
            .addQueryParam(FILTER_TAGS, filterTags).call(Entities.SUMMARY);
        return getResponse(EntitySummaryResult.class, clientResponse);
    }

    @Override
    public APIResult touch(String entityType, String entityName, String colo,
                           Boolean skipDryRun, String doAsUser) {
        Entities operation = Entities.TOUCH;
        ClientResponse clientResponse = new ResourceBuilder().path(operation.path, entityType, entityName)
            .addQueryParam(COLO, colo).addQueryParam(SKIP_DRYRUN, skipDryRun)
            .addQueryParam(DO_AS_OPT, doAsUser).call(operation);
        return getResponse(APIResult.class, clientResponse);
    }
    public InstancesResult getRunningInstances(String type, String entity, String colo, List<LifeCycle> lifeCycles,
                                      String filterBy, String orderBy, String sortOrder,
                                      Integer offset, Integer numResults, String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.RUNNING.path, type, entity)
            .addQueryParam(FILTER_BY, filterBy).addQueryParam(ORDER_BY, orderBy)
            .addQueryParam(SORT_ORDER, sortOrder).addQueryParam(OFFSET, offset)
            .addQueryParam(NUM_RESULTS, numResults).addQueryParam(COLO, colo)
            .addQueryParam(LIFECYCLE, lifeCycles, type).addQueryParam(USER, doAsUser).call(Instances.RUNNING);
        return getResponse(InstancesResult.class, clientResponse);
    }
    @Override
    public InstancesResult getStatusOfInstances(String type, String entity, String start, String end, String colo,
                                                List<LifeCycle> lifeCycles, String filterBy, String orderBy,
                                                String sortOrder, Integer offset, Integer numResults,
                                                String doAsUser, Boolean allAttempts) {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.STATUS.path, type, entity)
            .addQueryParam(START, start).addQueryParam(END, end).addQueryParam(COLO, colo)
            .addQueryParam(LIFECYCLE, lifeCycles, type).addQueryParam(FILTER_BY, filterBy)
            .addQueryParam(ORDER_BY, orderBy).addQueryParam(SORT_ORDER, sortOrder)
            .addQueryParam(OFFSET, offset).addQueryParam(NUM_RESULTS, numResults)
            .addQueryParam(ALL_ATTEMPTS, allAttempts).addQueryParam(USER, doAsUser).call(Instances.STATUS);
        return getResponse(InstancesResult.class, clientResponse);
    }

    public InstancesSummaryResult getSummaryOfInstances(String type, String entity,
                                        String start, String end,
                                        String colo, List<LifeCycle> lifeCycles,
                                        String filterBy, String orderBy, String sortOrder,
                                        String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.SUMMARY.path, type, entity)
            .addQueryParam(START, start).addQueryParam(END, end).addQueryParam(COLO, colo)
            .addQueryParam(LIFECYCLE, lifeCycles, type).addQueryParam(USER, doAsUser).call(Instances.SUMMARY);
        return getResponse(InstancesSummaryResult.class, clientResponse);
    }


    public FeedInstanceResult getFeedListing(String type, String entity, String start,
                                     String end, String colo, String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.KILL.path, type, entity)
            .addQueryParam(START, start).addQueryParam(END, end).addQueryParam(COLO, colo)
            .addQueryParam(USER, doAsUser).call(Instances.LISTING);
        return getResponse(FeedInstanceResult.class, clientResponse);
    }

    public InstancesResult searchInstances(String type, String nameSubsequence, String tagKeywords,
                                           String start, String end, String status, String orderBy,
                                           Integer offset, Integer numResults)  {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.SEARCH.path)
                .addQueryParam(ENTITY_TYPE, type)
                .addQueryParam(NAME_SUBSEQUENCE, nameSubsequence)
                .addQueryParam(TAG_KEYWORDS, tagKeywords)
                .addQueryParam(START, start)
                .addQueryParam(END, end)
                .addQueryParam(INSTANCE_STATUS, status)
                .addQueryParam(ORDER_BY, orderBy)
                .addQueryParam(OFFSET, offset)
                .addQueryParam(NUM_RESULTS, numResults)
                .call(Instances.SEARCH);
        return getResponse(InstancesResult.class, clientResponse);
    }

    public InstancesResult killInstances(String type, String entity, String start,
                                String end, String colo, String clusters,
                                String sourceClusters, List<LifeCycle> lifeCycles,
                                String doAsUser) throws UnsupportedEncodingException {
        InputStream props = getServletInputStream(clusters, sourceClusters, null);
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.KILL.path, type, entity)
            .addQueryParam(START, start).addQueryParam(END, end).addQueryParam(COLO, colo)
            .addQueryParam(LIFECYCLE, lifeCycles, type).addQueryParam(USER, doAsUser).call(Instances.KILL, props);
        return getResponse(InstancesResult.class, clientResponse);
    }

    public InstancesResult suspendInstances(String type, String entity, String start, String end, String colo,
                                            String clusters, String sourceClusters, List<LifeCycle> lifeCycles,
                                            String doAsUser) throws UnsupportedEncodingException {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.SUSPEND.path, type, entity)
            .addQueryParam(START, start).addQueryParam(END, end).addQueryParam(COLO, colo)
            .addQueryParam(LIFECYCLE, lifeCycles, type).addQueryParam(USER, doAsUser).call(Instances.SUSPEND);
        return getResponse(InstancesResult.class, clientResponse);
    }

    public InstancesResult resumeInstances(String type, String entity, String start, String end, String colo,
                                           String clusters, String sourceClusters, List<LifeCycle> lifeCycles,
                                           String doAsUser) throws UnsupportedEncodingException {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.RESUME.path, type, entity)
            .addQueryParam(START, start).addQueryParam(END, end).addQueryParam(COLO, colo)
            .addQueryParam(LIFECYCLE, lifeCycles, type).addQueryParam(USER, doAsUser).call(Instances.RESUME);
        return getResponse(InstancesResult.class, clientResponse);
    }

    public InstancesResult rerunInstances(String type, String entity, String start,
                                 String end, String filePath, String colo,
                                 String clusters, String sourceClusters, List<LifeCycle> lifeCycles,
                                 Boolean isForced, String doAsUser) throws IOException {

        StringBuilder buffer = new StringBuilder();
        if (filePath != null) {
            BufferedReader in = null;
            try {
                in = new BufferedReader(new FileReader(filePath));

                String str;
                while ((str = in.readLine()) != null) {
                    buffer.append(str).append("\n");
                }
            } finally {
                IOUtils.closeQuietly(in);
            }
        }
        String temp = (buffer.length() == 0) ? null : buffer.toString();
        InputStream props = getServletInputStream(clusters, sourceClusters, temp);
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.RERUN.path, type, entity)
            .addQueryParam(START, start).addQueryParam(END, end).addQueryParam(COLO, colo)
            .addQueryParam(LIFECYCLE, lifeCycles, type).addQueryParam(FORCE, isForced)
            .addQueryParam(USER, doAsUser).call(Instances.RERUN, props);
        return getResponse(InstancesResult.class, clientResponse);
    }

    public InstancesResult getLogsOfInstances(String type, String entity, String start,
                                              String end, String colo, String runId,
                                              List<LifeCycle> lifeCycles, String filterBy,
                                              String orderBy, String sortOrder, Integer offset,
                                              Integer numResults, String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(Instances.LOG.path, type, entity)
            .addQueryParam(START, start).addQueryParam(END, end).addQueryParam(COLO, colo)
            .addQueryParam(RUN_ID, runId).addQueryParam(LIFECYCLE, lifeCycles, type)
            .addQueryParam(FILTER_BY, filterBy).addQueryParam(ORDER_BY, orderBy)
            .addQueryParam(SORT_ORDER, sortOrder).addQueryParam(OFFSET, offset)
            .addQueryParam(NUM_RESULTS, numResults).addQueryParam(USER, doAsUser).call(Instances.LOG);
        return getResponse(InstancesResult.class, clientResponse);
    }

    public InstancesResult getParamsOfInstance(String type, String entity,
                                      String start, String colo,
                                      List<LifeCycle> lifeCycles,
                                      String doAsUser)
        throws UnsupportedEncodingException {
        if (!DateValidator.validate(start)) {
            throw new FalconCLIException("Start date is mandatory and should be"
                    + " a valid date in  YYYY-MM-DDTHH:MMZ format.");
        }

        ClientResponse clientResponse = new ResourceBuilder().path(Instances.PARAMS.path, type, entity)
            .addQueryParam(START, start).addQueryParam(LIFECYCLE, lifeCycles, type)
            .addQueryParam(USER, doAsUser).call(Instances.PARAMS);
        return getResponse(InstancesResult.class, clientResponse);
    }

    public String getThreadDump(String doAsUser) {
        return sendAdminRequest(AdminOperations.STACK, doAsUser);
    }

    @Override
    public String getVersion(String doAsUser) {
        return sendAdminRequest(AdminOperations.VERSION, doAsUser);
    }

    public int getStatus(String doAsUser) {
        AdminOperations job =  AdminOperations.VERSION;
        ClientResponse clientResponse = new ResourceBuilder().path(job.path).addQueryParam(DO_AS_OPT, doAsUser)
            .call(job);
        printClientResponse(clientResponse);
        return clientResponse.getStatus();
    }

    public ClientResponse setSafemode(String safemode, String doAsUser)  {
        AdminOperations job =  AdminOperations.SAFEMODE;
        ClientResponse clientResponse = new ResourceBuilder().path(job.path).path(safemode)
                .addQueryParam(DO_AS_OPT, doAsUser).call(job);
        printClientResponse(clientResponse);
        return clientResponse;
    }

    public String getDimensionList(String dimensionType, String cluster, String doAsUser)  {
        return sendMetadataDiscoveryRequest(MetadataOperations.LIST, dimensionType, null, cluster, doAsUser);
    }

    public String getReplicationMetricsDimensionList(String schedEntityType, String schedEntityName,
                                                     Integer numResults, String doAsUser) {
        return sendRequestForReplicationMetrics(MetadataOperations.LIST,
                schedEntityType, schedEntityName, numResults, doAsUser);
    }

    public LineageGraphResult getEntityLineageGraph(String pipelineName, String doAsUser) {
        MetadataOperations operation = MetadataOperations.LINEAGE;
        ClientResponse clientResponse = new ResourceBuilder().path(operation.path).addQueryParam(DO_AS_OPT, doAsUser)
            .addQueryParam(FalconCLIConstants.PIPELINE_OPT, pipelineName).call(operation);
        printClientResponse(clientResponse);
        checkIfSuccessful(clientResponse);
        return clientResponse.getEntity(LineageGraphResult.class);
    }

    public String getDimensionRelations(String dimensionType, String dimensionName,
                                        String doAsUser) {
        return sendMetadataDiscoveryRequest(MetadataOperations.RELATIONS, dimensionType, dimensionName, null, doAsUser);
    }

    private <T> T getResponse(Class<T> clazz, ClientResponse clientResponse) {
        printClientResponse(clientResponse);
        checkIfSuccessful(clientResponse);
        return clientResponse.getEntity(clazz);
    }

    private String getResponseAsString(ClientResponse clientResponse) {
        printClientResponse(clientResponse);
        checkIfSuccessful(clientResponse);
        return clientResponse.getEntity(String.class);
    }

    private class ResourceBuilder {
        WebResource resource;

        private ResourceBuilder path(String... paths) {
            for (String path : paths) {
                if (resource == null) {
                    resource = service.path(path);
                } else {
                    resource = resource.path(path);
                }
            }
            return this;
        }

        private ResourceBuilder addQueryParam(String paramName, Integer value) {
            if (value != null) {
                resource = resource.queryParam(paramName, value.toString());
            }
            return this;
        }

        private ResourceBuilder addQueryParam(String paramName, Boolean paramValue) {
            if (paramValue != null) {
                resource = resource.queryParam(paramName, String.valueOf(paramValue));
            }
            return this;
        }

        private ResourceBuilder addQueryParam(String paramName, String paramValue) {
            if (StringUtils.isNotBlank(paramValue)) {
                resource = resource.queryParam(paramName, paramValue);
            }
            return this;
        }

        private ResourceBuilder addQueryParam(String paramName, List<LifeCycle> lifeCycles,
                                             String type) {
            if (lifeCycles != null) {
                checkLifeCycleOption(lifeCycles, type);
                for (LifeCycle lifeCycle : lifeCycles) {
                    resource = resource.queryParam(paramName, lifeCycle.toString());
                }
            }
            return this;
        }

        private ClientResponse call(Entities entities) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(entities.mimeType).type(MediaType.TEXT_XML)
                .method(entities.method, ClientResponse.class);
        }

        private ClientResponse call(AdminOperations operation) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(operation.mimeType).type(MediaType.TEXT_XML)
                .method(operation.method, ClientResponse.class);
        }

        private ClientResponse call(MetadataOperations metadataOperations) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(metadataOperations.mimeType).type(MediaType.TEXT_XML)
                .method(metadataOperations.method, ClientResponse.class);
        }

        private ClientResponse call(Instances operation) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(operation.mimeType).type(MediaType.TEXT_XML)
                .method(operation.method, ClientResponse.class);
        }

        private ClientResponse call(ExtensionOperations operation) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                    .accept(operation.mimeType).type(MediaType.TEXT_XML)
                    .method(operation.method, ClientResponse.class);
        }

        private ClientResponse call(Entities operation, InputStream entityStream) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(operation.mimeType).type(MediaType.TEXT_XML)
                .method(operation.method, ClientResponse.class, entityStream);
        }

        private ClientResponse call(Instances operation, InputStream entityStream) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(operation.mimeType).type(MediaType.TEXT_XML)
                .method(operation.method, ClientResponse.class, entityStream);
        }

        private ClientResponse call(ExtensionOperations operation, InputStream entityStream) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                    .accept(operation.mimeType).type(MediaType.TEXT_XML)
                    .method(operation.method, ClientResponse.class, entityStream);
        }

        private ClientResponse call(ExtensionOperations submit, FormDataMultiPart formDataMultiPart) {
            return resource.header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                    .accept(submit.mimeType).type(MediaType.MULTIPART_FORM_DATA)
                    .method(submit.method, ClientResponse.class, formDataMultiPart);
        }
    }

    public FeedLookupResult reverseLookUp(String type, String path, String doAsUser) {
        Entities api = Entities.LOOKUP;
        ClientResponse response = new ResourceBuilder().path(api.path, type).addQueryParam(DO_AS_OPT, doAsUser)
            .addQueryParam(PATH, path).call(api);
        return getResponse(FeedLookupResult.class, response);
    }

    public FeedInstanceResult getFeedInstanceListing(String type, String entity, String start, String end, String colo
            , String doAsUser) {

        checkType(type);
        Instances api = Instances.LISTING;
        ClientResponse clientResponse = new ResourceBuilder().path(api.path, type, entity)
            .addQueryParam(COLO, colo).addQueryParam(DO_AS_OPT, doAsUser).addQueryParam(START, start)
            .addQueryParam(END, end).call(api);
        return getResponse(FeedInstanceResult.class, clientResponse);
    }


    public InstanceDependencyResult getInstanceDependencies(String entityType, String entityName, String instanceTime,
                                                            String colo) {
        checkType(entityType);
        Instances api = Instances.DEPENDENCY;
        ClientResponse clientResponse = new ResourceBuilder().path(api.path, entityType, entityName)
            .addQueryParam(COLO, colo).addQueryParam(INSTANCE_TIME, instanceTime).call(api);
        return getResponse(InstanceDependencyResult.class, clientResponse);
    }

    //RESUME CHECKSTYLE CHECK VisibilityModifierCheck

    private void checkLifeCycleOption(List<LifeCycle> lifeCycles, String type) {
        if (lifeCycles != null && !lifeCycles.isEmpty()) {
            EntityType entityType = EntityType.getEnum(type);
            for (LifeCycle lifeCycle : lifeCycles) {
                if (entityType != lifeCycle.getTag().getType()) {
                    throw new FalconCLIException("Incorrect lifecycle: " + lifeCycle + "for given type: " + type);
                }
            }
        }
    }

    private void checkType(String type) {
        if (type == null || type.isEmpty()) {
            throw new FalconCLIException("entity type is empty");
        } else {
            EntityType entityType = EntityType.getEnum(type);
            if (entityType == EntityType.CLUSTER) {
                throw new FalconCLIException(
                        "Instance management functions don't apply to Cluster entities");
            }
        }
    }

    private String sendAdminRequest(AdminOperations job, String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(job.path).addQueryParam(DO_AS_OPT, doAsUser)
            .call(job);
        return getResponseAsString(clientResponse);
    }

    private String sendRequestForReplicationMetrics(final MetadataOperations operation, final String schedEntityType,
                                                    final String schedEntityName, Integer numResults,
                                                    final String doAsUser) {
        WebResource resource = service.path(operation.path)
                .path(schedEntityName)
                .path(RelationshipType.REPLICATION_METRICS.getName())
                .path(FalconCLIConstants.LIST_OPT);

        if (StringUtils.isNotEmpty(schedEntityName)) {
            resource = resource.queryParam(FalconCLIConstants.TYPE_OPT, schedEntityType);
        }

        if (numResults != null) {
            resource = resource.queryParam(FalconCLIConstants.NUM_RESULTS_OPT, numResults.toString());
        }

        if (StringUtils.isNotEmpty(doAsUser)) {
            resource = resource.queryParam(FalconCLIConstants.DO_AS_OPT, doAsUser);
        }

        ClientResponse clientResponse = resource
                .header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(operation.mimeType).type(operation.mimeType)
                .method(operation.method, ClientResponse.class);

        printClientResponse(clientResponse);

        checkIfSuccessful(clientResponse);
        return clientResponse.getEntity(String.class);

    }

    private String sendMetadataDiscoveryRequest(final MetadataOperations operation,
                                                final String dimensionType,
                                                final String dimensionName,
                                                final String cluster,
                                                final String doAsUser) {
        WebResource resource;
        switch (operation) {
        case LIST:
            resource = service.path(operation.path)
                    .path(dimensionType)
                    .path(FalconCLIConstants.LIST_OPT);
            break;

        case RELATIONS:
            resource = service.path(operation.path)
                    .path(dimensionType)
                    .path(dimensionName)
                    .path(FalconCLIConstants.RELATIONS_OPT);
            break;

        default:
            throw new FalconCLIException("Invalid Metadata client Operation " + operation.toString());
        }

        if (!StringUtils.isEmpty(cluster)) {
            resource = resource.queryParam(FalconCLIConstants.CLUSTER_OPT, cluster);
        }

        if (StringUtils.isNotEmpty(doAsUser)) {
            resource = resource.queryParam(FalconCLIConstants.DO_AS_OPT, doAsUser);
        }

        ClientResponse clientResponse = resource
                .header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(operation.mimeType).type(operation.mimeType)
                .method(operation.method, ClientResponse.class);

        printClientResponse(clientResponse);

        checkIfSuccessful(clientResponse);
        return clientResponse.getEntity(String.class);
    }


    public String getVertex(String id, String doAsUser) {
        return sendMetadataLineageRequest(MetadataOperations.VERTICES, id, doAsUser);
    }

    public String getVertices(String key, String value, String doAsUser) {
        return sendMetadataLineageRequest(MetadataOperations.VERTICES, key, value, doAsUser);
    }

    public String getVertexEdges(String id, String direction, String doAsUser) {
        return sendMetadataLineageRequestForEdges(MetadataOperations.VERTICES, id, direction, doAsUser);
    }

    public String getEdge(String id, String doAsUser) {
        return sendMetadataLineageRequest(MetadataOperations.EDGES, id, doAsUser);
    }

    public APIResult enumerateExtensions()  {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.ENUMERATE.path)
                .call(ExtensionOperations.ENUMERATE);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult unregisterExtension(final String extensionName) {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.UNREGISTER.path, extensionName)
                .call(ExtensionOperations.UNREGISTER);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult getExtensionDetail(final String extensionName) {
        return getResponse(APIResult.class, getExtensionDetailResponse(extensionName));
    }

    public APIResult getExtensionJobDetails(final String jobName) {
        return getResponse(APIResult.class, getExtensionJobDetailsResponse(jobName));
    }

    private ClientResponse getExtensionJobDetailsResponse(final String jobName) {
        return new ResourceBuilder().path(ExtensionOperations.JOB_DETAILS.path, jobName)
                .call(ExtensionOperations.JOB_DETAILS);
    }

    private ClientResponse getExtensionDetailResponse(final String extensionName) {
        return  new ResourceBuilder().path(ExtensionOperations.DETAIL.path, extensionName)
                .call(ExtensionOperations.DETAIL);
    }

    public APIResult registerExtension(final String extensionName, final String packagePath, final String description) {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.REGISTER.path, extensionName).addQueryParam(PATH, packagePath)
                .addQueryParam(FalconCLIConstants.DESCRIPTION, description)
                .call(ExtensionOperations.REGISTER);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult enableExtension(final String extensionName) {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.ENABLE.path, extensionName).call(ExtensionOperations.ENABLE);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult disableExtension(final String extensionName) {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.DISABLE.path, extensionName).call(ExtensionOperations.DISABLE);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult getExtensionDefinition(final String extensionName)  {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.DEFINITION.path, extensionName)
                .call(ExtensionOperations.DEFINITION);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult getExtensionDescription(final String extensionName)  {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.DESCRIBE.path, extensionName)
                .call(ExtensionOperations.DESCRIBE);
        return getResponse(APIResult.class, clientResponse);
    }

    @Override
    public APIResult submitExtensionJob(final String extensionName, final String jobName, final String configPath,
                                        final String doAsUser) {
        FormDataMultiPart entitiesForm = getEntitiesForm(extensionName, jobName, configPath);
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.SUBMIT.path, extensionName)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .addQueryParam(JOB_NAME_OPT, jobName)
                .call(ExtensionOperations.SUBMIT, entitiesForm);
        return getResponse(APIResult.class, clientResponse);
    }

    private FormDataMultiPart getEntitiesForm(String extensionName, String jobName, String configPath) {
        InputStream configStream = getServletInputStream(configPath);
        List<Entity> entities = validateExtensionAndGetEntities(extensionName, jobName, configStream);
        FormDataMultiPart formDataMultiPart = new FormDataMultiPart();

        if (entities != null && !entities.isEmpty()) {
            for (Entity entity : entities) {
                if (EntityType.FEED.equals(entity.getEntityType())) {
                    formDataMultiPart.field(FEEDS, entity, MediaType.APPLICATION_XML_TYPE);
                } else if (EntityType.PROCESS.equals(entity.getEntityType())) {
                    formDataMultiPart.field(PROCESSES, entity, MediaType.APPLICATION_XML_TYPE);
                }
            }
        }
        formDataMultiPart.field(CONFIG, configStream, MediaType.APPLICATION_OCTET_STREAM_TYPE);
        try {
            formDataMultiPart.close();
        } catch (IOException e) {
            throw new FalconCLIException("Submit failed. Failed to submit entities", e);
        }
        return formDataMultiPart;
    }

    private List<Entity> validateExtensionAndGetEntities(String extensionName, String jobName,
                                                         InputStream configStream) {
        JSONObject extensionDetailJson;
        if (StringUtils.isBlank(extensionName)) {
            extensionName = ExtensionHandler.getExtensionName(jobName, getExtensionJobDetailJson(jobName));
        }
        extensionDetailJson = getExtensionDetailJson(extensionName);
        String extensionType = ExtensionHandler.getExtensionType(extensionName, extensionDetailJson);
        String extensionBuildLocation = ExtensionHandler.getExtensionLocation(extensionName, extensionDetailJson);
        return getEntities(extensionName, jobName, configStream, extensionType,
                extensionBuildLocation);
    }

    private JSONObject getExtensionDetailJson(String extensionName) {
        ClientResponse clientResponse = getExtensionDetailResponse(extensionName);

        JSONObject extensionDetailJson;
        try {
            extensionDetailJson = new JSONObject(getResponse(APIResult.class, clientResponse).getMessage());
        } catch (JSONException e) {
            throw new FalconCLIException("Failed to get details for the given extension", e);
        }
        return extensionDetailJson;
    }
    private JSONObject getExtensionJobDetailJson(String jobName) {
        ClientResponse clientResponse = getExtensionJobDetailsResponse(jobName);
        JSONObject extensionJobDetailJson;
        try {
            extensionJobDetailJson = new JSONObject(getResponse(APIResult.class, clientResponse).getMessage());
        } catch (JSONException e) {
            throw new FalconCLIException("Failed to get details for the given extension", e);
        }
        return extensionJobDetailJson;
    }

    private List<Entity> getEntities(String extensionName, String jobName, InputStream configStream,
                                     String extensionType, String extensionBuildLocation) {
        List<Entity> entities = null;
        if (!extensionType.equals(ExtensionType.CUSTOM.name())) {
            try {
                entities = ExtensionHandler.loadAndPrepare(extensionName, jobName, configStream,
                        extensionBuildLocation);
            } catch (Exception e) {
                throw new FalconCLIException("Error in building the extension", e);
            }
            if (entities == null || entities.isEmpty()) {
                throw new FalconCLIException("No entities got built for the given extension");
            }
        }
        return entities;
    }

    public APIResult submitAndScheduleExtensionJob(final String extensionName, final String jobName,
                                                   final String configPath, final String doAsUser)  {
        FormDataMultiPart entitiesForm = getEntitiesForm(extensionName, jobName, configPath);
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.SUBMIT_AND_SCHEDULE.path, extensionName)
                .addQueryParam(JOB_NAME_OPT, jobName)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .call(ExtensionOperations.SUBMIT_AND_SCHEDULE, entitiesForm);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult updateExtensionJob(final String jobName, final String configPath, final String doAsUser) {
        FormDataMultiPart entitiesForm = getEntitiesForm(null, jobName, configPath);
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.UPDATE.path, jobName)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .call(ExtensionOperations.UPDATE, entitiesForm);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult validateExtensionJob(final String extensionName, final String jobName,
                                          final String configPath, final String doAsUser) {
        String extensionType = ExtensionHandler.getExtensionType(extensionName, getExtensionDetailJson(extensionName));
        InputStream configStream = getServletInputStream(configPath);
        if (ExtensionType.TRUSTED.name().equalsIgnoreCase(extensionType)) {
            ClientResponse clientResponse = new ResourceBuilder()
                    .path(ExtensionOperations.VALIDATE.path, extensionName)
                    .addQueryParam(DO_AS_OPT, doAsUser)
                    .call(ExtensionOperations.VALIDATE, configStream);
            return getResponse(APIResult.class, clientResponse);
        } else {
            validateExtensionAndGetEntities(extensionName, jobName, configStream);
            return new APIResult(APIResult.Status.SUCCEEDED, "Validated successfully");
        }
    }

    public APIResult scheduleExtensionJob(String jobName, final String coloExpr, final String doAsUser)  {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.SCHEDULE.path, jobName)
                .addQueryParam(COLO, coloExpr)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .call(ExtensionOperations.SCHEDULE);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult suspendExtensionJob(final String jobName, final String doAsUser)  {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.SUSPEND.path, jobName)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .call(ExtensionOperations.SUSPEND);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult resumeExtensionJob(final String jobName, final String doAsUser)  {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.RESUME.path, jobName)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .call(ExtensionOperations.RESUME);
        return getResponse(APIResult.class, clientResponse);
    }

    public APIResult deleteExtensionJob(final String jobName, final String doAsUser)  {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.DELETE.path, jobName)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .call(ExtensionOperations.DELETE);
        return getResponse(APIResult.class, clientResponse);
    }

    public ExtensionJobList listExtensionJob(final String extensionName, final String doAsUser,
                                             final String sortOrder, final String offset,
                                             final String numResults, final String fields)  {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.LIST.path, extensionName)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .addQueryParam(FIELDS, fields)
                .addQueryParam(SORT_ORDER, sortOrder)
                .addQueryParam(OFFSET, offset)
                .addQueryParam(NUM_RESULTS, numResults)
                .call(ExtensionOperations.LIST);
        return getResponse(ExtensionJobList.class, clientResponse);
    }

    public ExtensionInstanceList listExtensionInstance(final String jobName, final String doAsUser, final String fields,
                                                       final String start, final String end, final String status,
                                                       final String orderBy, final String sortOrder,
                                                       final String offset, final String numResults) {
        ClientResponse clientResponse = new ResourceBuilder()
                .path(ExtensionOperations.INSTANCES.path, jobName)
                .addQueryParam(DO_AS_OPT, doAsUser)
                .addQueryParam(FIELDS, fields)
                .addQueryParam(START, start)
                .addQueryParam(END, end)
                .addQueryParam(INSTANCE_STATUS, status)
                .addQueryParam(ORDER_BY, orderBy)
                .addQueryParam(SORT_ORDER, sortOrder)
                .addQueryParam(OFFSET, offset)
                .addQueryParam(NUM_RESULTS, numResults)
                .call(ExtensionOperations.INSTANCES);
        return getResponse(ExtensionInstanceList.class, clientResponse);
    }

    private String sendExtensionRequest(final ExtensionOperations operation,
                                        final String extensionName)  {
        WebResource resource;
        switch (operation) {
        case ENUMERATE:
            resource = service.path(operation.path);
            break;

        case DESCRIBE:
        case DEFINITION:
            resource = service.path(operation.path).path(extensionName);
            break;

        default:
            throw new FalconCLIException("Invalid extension client Operation " + operation.toString());
        }

        ClientResponse clientResponse = resource
                .header("Cookie", AUTH_COOKIE_EQ + authenticationToken)
                .accept(operation.mimeType).type(operation.mimeType)
                .method(operation.method, ClientResponse.class);

        checkIfSuccessful(clientResponse);
        return clientResponse.getEntity(String.class);
    }

    private String sendMetadataLineageRequest(MetadataOperations job, String id,
                                              String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(job.path, id).addQueryParam(DO_AS_OPT, doAsUser)
            .call(job);
        return getResponseAsString(clientResponse);
    }

    private String sendMetadataLineageRequest(MetadataOperations job, String key,
                                              String value, String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(job.path).addQueryParam(DO_AS_OPT, doAsUser)
            .addQueryParam(KEY, key).addQueryParam(VALUE, value).call(job);
        return getResponseAsString(clientResponse);
    }

    private String sendMetadataLineageRequestForEdges(MetadataOperations job, String id,
                                                      String direction, String doAsUser) {
        ClientResponse clientResponse = new ResourceBuilder().path(job.path, id, direction)
            .addQueryParam(DO_AS_OPT, doAsUser).call(job);
        return getResponseAsString(clientResponse);
    }

    private void checkIfSuccessful(ClientResponse clientResponse) {
        Response.Status.Family statusFamily = clientResponse.getClientResponseStatus().getFamily();
        if (statusFamily != Response.Status.Family.SUCCESSFUL && statusFamily != Response.Status.Family.INFORMATIONAL) {
            throw FalconCLIException.fromReponse(clientResponse);
        }
    }

    private void printClientResponse(ClientResponse clientResponse) {
        if (getDebugMode()) {
            OUT.get().println(clientResponse.toString());
        }
    }
}
