import six


def _ensure_path(girder_client, girder_folders, parent, path):
    """
    Ensure that a particular path exists in Girder as a set of folders. If
    it doesn't exist create it.

    :params girder_client: The Girder client to use to access Girder.
    :params girder_folders: A map of paths to existing Girder folder ids.
    :params parent: The parent Girder folder that this path should exist in.
    :params path: The path that should exist.

    :returns The folderId for the last folder in the path.
    """
    if path in girder_folders:
        return girder_folders[path]

    parts = path.split('/')

    # Default our parent_id to parent, however this may be updated if we already
    # have folders created in Girder, see loop below.
    parent_id = parent

    # First identify the folders we have already have in Girder
    index = 0
    for i in range(len(parts), 0, -1):
        part = '/'.join(parts[:i])
        if part in girder_folders:
            parent_id = girder_folders[part]
            index = i
            break

    # Now walk through the parts of the path we need to create
    i = index + 1
    parent_created = False
    for name in parts[index:]:
        path = '/'.join(parts[:i])
        # Check if the folder already exists
        if not parent_created:
            folders = girder_client.listFolder(parent_id, name=name)
            try:
                folder_id = six.next(folders)['_id']
                girder_folders[path] = folder_id
                parent_id = folder_id
                i += 1
                continue
            except StopIteration:
                pass

        # Create the folder
        folder = girder_client.createFolder(parent_id, name,
                                            parentType='folder')
        # Don't bother checking if folders have already been created ...
        parent_created = True
        parent_id = folder['_id']
        girder_folders[path] = parent_id

        i += 1

    return parent_id