package com.box.sdk;

import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.Iterator;

import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;

public final class BoxFolder extends BoxItem implements Iterable<BoxItem> {
    private static final String UPLOAD_FILE_URL_BASE = "https://upload.box.com/api/2.0/";
    private static final URLTemplate CREATE_FOLDER_URL = new URLTemplate("folders");
    private static final URLTemplate COPY_FOLDER_URL = new URLTemplate("folders/%s/copy");
    private static final URLTemplate DELETE_FOLDER_URL = new URLTemplate("folders/%s?recursive=%b");
    private static final URLTemplate FOLDER_INFO_URL_TEMPLATE = new URLTemplate("folders/%s");
    private static final URLTemplate UPLOAD_FILE_URL = new URLTemplate("files/content");

    private final URL folderURL;

    public BoxFolder(BoxAPIConnection api, String id) {
        super(api, id);

        this.folderURL = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), this.getID());
    }

    public static BoxFolder getRootFolder(BoxAPIConnection api) {
        return new BoxFolder(api, "0");
    }

    public BoxFolder.Info getInfo() {
        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), this.folderURL, "GET");
        BoxJSONResponse response = (BoxJSONResponse) request.send();
        return new Info(response.getJSON());
    }

    public BoxFolder.Info getInfo(String... fields) {
        StringBuilder fieldsStringBuilder = new StringBuilder();
        for (String field : fields) {
            fieldsStringBuilder.append(field);
            fieldsStringBuilder.append(",");
        }
        fieldsStringBuilder.deleteCharAt(fieldsStringBuilder.length() - 1);

        String[][] queryParams = new String[][] {{"fields", fieldsStringBuilder.toString()}};
        URL url = FOLDER_INFO_URL_TEMPLATE.build(this.getAPI().getBaseURL(), queryParams, this.getID());
        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "GET");
        BoxJSONResponse response = (BoxJSONResponse) request.send();
        return new Info(response.getJSON());
    }

    public void updateInfo(BoxFolder.Info info) {
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), this.folderURL, "PUT");
        request.setBody(info.toString());
        BoxJSONResponse response = (BoxJSONResponse) request.send();
        JsonObject jsonObject = JsonObject.readFrom(response.getJSON());
        info.updateFromJSON(jsonObject);
    }

    public BoxFolder.Info copy(BoxFolder destination) {
        return this.copy(destination, null);
    }

    public BoxFolder.Info copy(BoxFolder destination, String newName) {
        return this.copy(destination.getID(), newName);
    }

    public BoxFolder.Info copy(String destinationID) {
        return this.copy(destinationID, null);
    }

    public BoxFolder.Info copy(String destinationID, String newName) {
        URL url = COPY_FOLDER_URL.build(this.getAPI().getBaseURL(), this.getID());
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), url, "POST");

        JsonObject parent = new JsonObject();
        parent.add("id", destinationID);

        JsonObject copyInfo = new JsonObject();
        copyInfo.add("parent", parent);
        if (newName != null) {
            copyInfo.add("name", newName);
        }

        request.setBody(copyInfo.toString());
        BoxJSONResponse response = (BoxJSONResponse) request.send();
        JsonObject responseJSON = JsonObject.readFrom(response.getJSON());
        BoxFolder copiedFolder = new BoxFolder(this.getAPI(), responseJSON.get("id").asString());
        return copiedFolder.new Info(responseJSON);
    }

    public BoxFolder createFolder(String name) {
        JsonObject parent = new JsonObject();
        parent.add("id", this.getID());

        JsonObject newFolder = new JsonObject();
        newFolder.add("name", name);
        newFolder.add("parent", parent);

        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), CREATE_FOLDER_URL.build(this.getAPI().getBaseURL()),
            "POST");
        request.setBody(newFolder.toString());
        BoxJSONResponse response = (BoxJSONResponse) request.send();
        JsonObject createdFolder = JsonObject.readFrom(response.getJSON());

        return new BoxFolder(this.getAPI(), createdFolder.get("id").asString());
    }

    public void delete(boolean recursive) {
        URL url = DELETE_FOLDER_URL.build(this.getAPI().getBaseURL(), this.getID(), recursive);
        BoxAPIRequest request = new BoxAPIRequest(this.getAPI(), url, "DELETE");
        BoxAPIResponse response = request.send();
        response.disconnect();
    }

    public void move(BoxFolder destination) {
        this.move(destination.getID());
    }

    public void move(String destinationID) {
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), this.folderURL, "PUT");

        JsonObject parent = new JsonObject();
        parent.add("id", destinationID);

        JsonObject updateInfo = new JsonObject();
        updateInfo.add("parent", parent);

        request.setBody(updateInfo.toString());
        BoxAPIResponse response = request.send();
        response.disconnect();
    }

    public void rename(String newName) {
        BoxJSONRequest request = new BoxJSONRequest(this.getAPI(), this.folderURL, "PUT");

        JsonObject updateInfo = new JsonObject();
        updateInfo.add("name", newName);

        request.setBody(updateInfo.toString());
        BoxAPIResponse response = request.send();
        response.disconnect();
    }

    public BoxFile uploadFile(InputStream fileContent, String name, Date created, Date modified) {
        URL uploadURL = UPLOAD_FILE_URL.build(UPLOAD_FILE_URL_BASE);
        BoxMultipartRequest request = new BoxMultipartRequest(getAPI(), uploadURL);
        request.putField("parent_id", getID());
        request.setFile(fileContent, name);

        BoxJSONResponse response = (BoxJSONResponse) request.send();
        JsonObject collection = JsonObject.readFrom(response.getJSON());
        JsonArray entries = collection.get("entries").asArray();
        String uploadedFileID = entries.get(0).asObject().get("id").asString();

        return new BoxFile(getAPI(), uploadedFileID);
    }

    public Iterator<BoxItem> iterator() {
        return new BoxItemIterator(BoxFolder.this.getAPI(), BoxFolder.this.getID());
    }

    public class Info extends BoxItem.Info<BoxFolder> {
        public Info() {
            super();
        }

        public Info(String json) {
            super(json);
        }

        protected Info(JsonObject jsonObject) {
            super(jsonObject);
        }

        @Override
        public BoxFolder getResource() {
            return BoxFolder.this;
        }

        @Override
        protected void parseJSONMember(JsonObject.Member member) {
            super.parseJSONMember(member);

            String memberName = member.getName();
            switch (memberName) {
                default:
                    break;
            }
        }
    }
}

@@ -2700,251 +2700,8 @@
 ) %7B%0A
-        return this.copy(destination.getID(), newName);%0A    %7D%0A%0A    public BoxFolder.Info copy(String destinationID) %7B%0A        return this.copy(destinationID, null);%0A    %7D%0A%0A    public BoxFolder.Info copy(String destinationID, String newName) %7B%0A
     
@@ -2771,32 +2771,32 @@
  this.getID());%0A
+
         BoxJSONR
@@ -2935,34 +2935,40 @@
 id%22, destination
-ID
+.getID()
 );%0A%0A        Json

Remove some overloaded copy methods from BoxFolder