/**
 * 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.
 */

/*
 * Camel Api Route test generated by camel-component-util-maven-plugin
 * Generated on: Tue Jun 24 22:42:08 PDT 2014
 */
package org.apache.camel.component.box;

import java.util.HashMap;
import java.util.Map;

import com.box.boxjavalibv2.dao.BoxCollection;
import com.box.boxjavalibv2.dao.BoxGroup;
import com.box.boxjavalibv2.dao.BoxGroupMembership;
import com.box.boxjavalibv2.requests.requestobjects.BoxGroupMembershipRequestObject;
import com.box.boxjavalibv2.requests.requestobjects.BoxGroupRequestObject;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.box.internal.BoxApiCollection;
import org.apache.camel.component.box.internal.IBoxGroupsManagerApiMethod;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Test class for com.box.boxjavalibv2.resourcemanagers.IBoxGroupsManager APIs.
 */
public class IBoxGroupsManagerIntegrationTest extends AbstractBoxTestSupport {

    private static final Logger LOG = LoggerFactory.getLogger(IBoxGroupsManagerIntegrationTest.class);
    private static final String PATH_PREFIX = BoxApiCollection.getCollection().getApiName(IBoxGroupsManagerApiMethod.class).getName();

    private static final String CAMEL_TEST_GROUP = "CamelTestGroup";

    public BoxGroup createGroup() throws Exception {
        // using com.box.boxjavalibv2.requests.requestobjects.BoxGroupRequestObject message body for single parameter "groupRequest"
        final BoxGroupRequestObject requestObject = BoxGroupRequestObject.createGroupRequestObject(CAMEL_TEST_GROUP);
        BoxGroup result = requestBody("direct://CREATEGROUP", requestObject);

        assertNotNull("createGroup result", result);
        return result;
    }

    @Test
    public void testCreateGroup1() throws Exception {
        // using String message body for single parameter "name"
        BoxGroup result = requestBody("direct://CREATEGROUP_1", CAMEL_TEST_GROUP);

        assertNotNull("createGroup result", result);
        LOG.debug("createGroup: " + result);

        deleteGroup(result.getId());
    }

    public BoxGroupMembership createMembership(String groupId) throws Exception {
        // using com.box.boxjavalibv2.requests.requestobjects.BoxGroupMembershipRequestObject message body for single parameter "groupMembershipRequest"
        final BoxGroupMembershipRequestObject requestObject =
                BoxGroupMembershipRequestObject.addMembershipRequestObject(groupId, testUserId, BoxGroupMembership.ROLE_MEMBER);
        BoxGroupMembership result = requestBody("direct://CREATEMEMBERSHIP", requestObject);

        assertNotNull("createMembership result", result);
        return result;
    }

    @Test
    public void testCreateMembership1() throws Exception {
        final BoxGroup group = createGroup();

        try {
            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.groupId", group.getId());
            // parameter type is String
            headers.put("CamelBox.userId", testUserId);
            // parameter type is String
            headers.put("CamelBox.role", BoxGroupMembership.ROLE_MEMBER);

            BoxGroupMembership result = requestBodyAndHeaders("direct://CREATEMEMBERSHIP_1", null, headers);

            assertNotNull("createMembership result", result);
            LOG.debug("createMembership: " + result);
        } finally {
            deleteGroup(group.getId());
        }
    }

    public void deleteGroup(String groupId) throws Exception {
        final Map<String, Object> headers = new HashMap<String, Object>();
        // parameter type is String
        headers.put("CamelBox.groupId", groupId);
        // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//        headers.put("CamelBox.defaultRequest", null);

        requestBodyAndHeaders("direct://DELETEGROUP", null, headers);
    }

    @Test
    public void testDeleteMembership() throws Exception {
        final BoxGroup group = createGroup();

        try {
            final BoxGroupMembership membership = createMembership(group.getId());

            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.membershipId", membership.getId());
            // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//            headers.put("CamelBox.defaultRequest", null);
            requestBodyAndHeaders("direct://DELETEMEMBERSHIP", null, headers);
        } finally {
            deleteGroup(group.getId());
        }
    }

    @Test
    public void testGetAllCollaborations() throws Exception {
        final BoxGroup group = createGroup();
        try {
            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.groupId", group.getId());
            // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//            headers.put("CamelBox.defaultRequest", null);

            BoxCollection result = requestBodyAndHeaders("direct://GETALLCOLLABORATIONS", null, headers);

            assertNotNull("getAllCollaborations result", result);
            LOG.debug("getAllCollaborations: " + result);
        } finally {
            deleteGroup(group.getId());
        }
    }

    @Test
    public void testGetAllGroups() throws Exception {
        // using com.box.restclientv2.requestsbase.BoxDefaultRequestObject message body for single parameter "defaultRequest"
        BoxCollection result = requestBody("direct://GETALLGROUPS", null);

        assertNotNull("getAllGroups result", result);
        LOG.debug("getAllGroups: " + result);
    }

    @Test
    public void testGetMembership() throws Exception {
        final BoxGroup group = createGroup();

        try {
            final BoxGroupMembership membership = createMembership(group.getId());

            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.membershipId", membership.getId());
            // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
//            headers.put("CamelBox.defaultRequest", null);

            BoxGroupMembership result = requestBodyAndHeaders("direct://GETMEMBERSHIP", null, headers);

            assertNotNull("getMembership result", result);
            LOG.debug("getMembership: " + result);
        } finally {
            deleteGroup(group.getId());
        }
    }

    @Test
    public void testGetMemberships() throws Exception {
        final BoxGroup group = createGroup();

        try {
            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.groupId", group.getId());
            // parameter type is com.box.restclientv2.requestsbase.BoxDefaultRequestObject
            headers.put("CamelBox.defaultRequest", null);

            BoxCollection result = requestBodyAndHeaders("direct://GETMEMBERSHIPS", null, headers);

            assertNotNull("getMemberships result", result);
            LOG.debug("getMemberships: " + result);
        } finally {
            deleteGroup(group.getId());
        }
    }

    @Test
    public void testUpdateGroup() throws Exception {
        final BoxGroup group = createGroup();

        try {
            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.groupId", group.getId());
            // parameter type is com.box.boxjavalibv2.requests.requestobjects.BoxGroupRequestObject
            final BoxGroupRequestObject requestObject =
                    BoxGroupRequestObject.updateGroupRequestObject(CAMEL_TEST_GROUP + "_Updated");
            headers.put("CamelBox.groupRequest", requestObject);

            BoxGroup result = requestBodyAndHeaders("direct://UPDATEGROUP", null, headers);

            assertNotNull("updateGroup result", result);
            LOG.debug("updateGroup: " + result);
        } finally {
            deleteGroup(group.getId());
        }
    }

    @Test
    public void testUpdateMembership() throws Exception {
        final BoxGroup group = createGroup();

        try {
            final BoxGroupMembership membership = createMembership(group.getId());

            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.membershipId", membership.getId());
            // parameter type is com.box.boxjavalibv2.requests.requestobjects.BoxGroupMembershipRequestObject
            final BoxGroupMembershipRequestObject requestObject =
                    BoxGroupMembershipRequestObject.updateMembershipRequestObject(BoxGroupMembership.ROLE_ADMIN);
            headers.put("CamelBox.groupMembershipRequest", requestObject);

            BoxGroupMembership result = requestBodyAndHeaders("direct://UPDATEMEMBERSHIP", null, headers);

            assertNotNull("updateMembership result", result);
            LOG.debug("updateMembership: " + result);
        } finally {
            deleteGroup(group.getId());
        }
    }

    @Test
    public void testUpdateMembership1() throws Exception {
        final BoxGroup group = createGroup();

        try {
            final BoxGroupMembership membership = createMembership(group.getId());

            final Map<String, Object> headers = new HashMap<String, Object>();
            // parameter type is String
            headers.put("CamelBox.membershipId", membership.getId());
            // parameter type is String
            headers.put("CamelBox.role", BoxGroupMembership.ROLE_ADMIN);

            BoxGroupMembership result = requestBodyAndHeaders("direct://UPDATEMEMBERSHIP_1", null, headers);

            assertNotNull("updateMembership result", result);
            LOG.debug("updateMembership: " + result);
        } finally {
            deleteGroup(group.getId());
        }
    }

    @Override
    protected RouteBuilder createRouteBuilder() throws Exception {
        return new RouteBuilder() {
            public void configure() {
                // test route for createGroup
                from("direct://CREATEGROUP")
                        .to("box://" + PATH_PREFIX + "/createGroup?inBody=groupRequest");

                // test route for createGroup
                from("direct://CREATEGROUP_1")
                        .to("box://" + PATH_PREFIX + "/createGroup?inBody=name");

                // test route for createMembership
                from("direct://CREATEMEMBERSHIP")
                        .to("box://" + PATH_PREFIX + "/createMembership?inBody=groupMembershipRequest");

                // test route for createMembership
                from("direct://CREATEMEMBERSHIP_1")
                        .to("box://" + PATH_PREFIX + "/createMembership");

                // test route for deleteGroup
                from("direct://DELETEGROUP")
                        .to("box://" + PATH_PREFIX + "/deleteGroup");

                // test route for deleteMembership
                from("direct://DELETEMEMBERSHIP")
                        .to("box://" + PATH_PREFIX + "/deleteMembership");

                // test route for getAllCollaborations
                from("direct://GETALLCOLLABORATIONS")
                        .to("box://" + PATH_PREFIX + "/getAllCollaborations");

                // test route for getAllGroups
                from("direct://GETALLGROUPS")
                        .to("box://" + PATH_PREFIX + "/getAllGroups?inBody=defaultRequest");

                // test route for getMembership
                from("direct://GETMEMBERSHIP")
                        .to("box://" + PATH_PREFIX + "/getMembership");

                // test route for getMemberships
                from("direct://GETMEMBERSHIPS")
                        .to("box://" + PATH_PREFIX + "/getMemberships");

                // test route for updateGroup
                from("direct://UPDATEGROUP")
                        .to("box://" + PATH_PREFIX + "/updateGroup");

                // test route for updateMembership
                from("direct://UPDATEMEMBERSHIP")
                        .to("box://" + PATH_PREFIX + "/updateMembership");

                // test route for updateMembership
                from("direct://UPDATEMEMBERSHIP_1")
                        .to("box://" + PATH_PREFIX + "/updateMembership");

            }
        };
    }
}
