UUID IInventoryItemServiceInterface.Copy(UUID principalID, UUID id, UUID newFolder)
        {
            var headers = new Dictionary <string, string>
            {
                ["Destination"] = $"{m_CapabilityUri}category/{newFolder}"
            };
            Map            res;
            HttpStatusCode statuscode;

            using (Stream s = new HttpClient.Copy($"{m_CapabilityUri}item/{id}")
            {
                TimeoutMs = TimeoutMs,
                Headers = headers,
                DisableExceptions = HttpClient.Request.DisableExceptionFlags.DisableForbidden | HttpClient.Request.DisableExceptionFlags.DisableGone
            }.ExecuteStreamRequest(out statuscode))
            {
                switch (statuscode)
                {
                case HttpStatusCode.OK:
                    break;

                case HttpStatusCode.Forbidden:
                    throw new InventoryItemNotCopiableException(id);

                case HttpStatusCode.Gone:
                    throw new InventoryItemNotFoundException(id);

                default:
                    throw new InvalidParentFolderIdException();
                }
                res = (Map)LlsdXml.Deserialize(s);
            }

            AnArray created_items;

            if (!res.TryGetValue("_created_items", out created_items) || created_items.Count != 1)
            {
                throw new InventoryItemNotStoredException();
            }
            return(created_items[0].AsUUID);
        }
        InventoryTree IInventoryFolderServiceInterface.Copy(UUID principalID, UUID folderID, UUID toFolderID)
        {
            var headers = new Dictionary <string, string>
            {
                ["Destination"] = $"{m_CapabilityUri}category/{toFolderID}"
            };
            Map            res;
            HttpStatusCode statuscode;

            using (Stream s = new HttpClient.Copy($"{m_CapabilityUri}category/{folderID}")
            {
                TimeoutMs = TimeoutMs,
                Headers = headers,
                DisableExceptions = HttpClient.Request.DisableExceptionFlags.DisableForbidden |
                                    HttpClient.Request.DisableExceptionFlags.DisableGone
            }.ExecuteStreamRequest(out statuscode))
            {
                switch (statuscode)
                {
                case HttpStatusCode.OK:
                    break;

                case HttpStatusCode.Forbidden:
                    throw new InventoryItemNotCopiableException();

                case HttpStatusCode.Gone:
                    throw new InventoryFolderNotFoundException(folderID);

                default:
                    throw new InvalidParentFolderIdException();
                }
                res = (Map)LlsdXml.Deserialize(s);
            }

            var copiedFolder = new InventoryTree
            {
                Name           = res["name"].ToString(),
                DefaultType    = (AssetType)res["type_default"].AsInt,
                ParentFolderID = res["parent_id"].AsUUID,
                Version        = res["version"].AsInt,
                Owner          = new UGUI(res["agent_id"].AsUUID),
                ID             = res["category_id"].AsUUID
            };
            var stack      = new List <Map>();
            var parentTree = new Dictionary <UUID, InventoryTree>();

            parentTree.Add(copiedFolder.ID, copiedFolder);
            stack.Add(res);
            while (stack.Count > 0)
            {
                res = stack[0];
                stack.RemoveAt(0);
                Map           embmap;
                Map           foldermap;
                InventoryTree parentFolder = parentTree[res["category_id"].AsUUID];
                parentFolder.Items.AddRange(ExtractItems(res));
                if (res.TryGetValue("_embedded", out embmap) && embmap.TryGetValue("categories", out foldermap))
                {
                    foreach (KeyValuePair <string, IValue> kvp in foldermap)
                    {
                        var folderdata = kvp.Value as Map;
                        if (folderdata == null)
                        {
                            continue;
                        }
                        var folder = new InventoryTree(folderdata["category_id"].AsUUID)
                        {
                            Name           = folderdata["name"].ToString(),
                            DefaultType    = (AssetType)folderdata["type_default"].AsInt,
                            ParentFolderID = folderdata["parent_id"].AsUUID,
                            Version        = folderdata["version"].AsInt,
                            Owner          = new UGUI(folderdata["agent_id"].AsUUID)
                        };
                        stack.Add(folderdata);
                        parentFolder.Folders.Add(folder);
                    }
                }
            }
            return(copiedFolder);
        }