syntax = "proto3";

import "common.proto";
import "file.proto";

package fs;


message FS {
	string type = 1;
	bool is_versioned = 2;
	bool writable = 3;
	string name = 4;
	// impl is a reference to object with methods of either
	// ReadonlyFS or WritableFS
	common.ObjectReference impl = 5;
	bool is_synced = 6;
}


// ==== ReadonlyFS referable as impl object ====

// --- ReadonlyFS.checkFolderPresence ---
// Request body is CheckPresenceRequestBody
// Reply body is common.BooleanValue

message CheckPresenceRequestBody {
	string path = 1;
	common.BooleanValue throw_if_missing = 2;
}

// --- ReadonlyFS.checkFilePresence ---
// Request body is CheckPresenceRequestBody
// Reply body is common.BooleanValue

// --- ReadonlyFS.checkLinkPresence ---
// Request body is CheckPresenceRequestBody
// Reply body is common.BooleanValue

// --- ReadonlyFS.stat ---
// Request body is PathOnlyRequestBody
// Reply body is file.StatsMsg

message PathOnlyRequestBody {
	string path = 1;
}

// --- ReadonlyFS.getXAttr ---
// Reply body is file.XAttrValue
message GetXAttrRequestBody {
	string path = 1;
	string xa_name = 2;
}

// --- ReadonlyFS.listXAttrs ---
// Request body is PathOnlyRequestBody
// Reply body is common.StringArrayValue

// --- ReadonlyFS.readLink ---
// Request body is PathOnlyRequestBody
// Reply body is SymLink

message SymLink {
	bool readonly = 1;
	common.BooleanValue is_file = 2;
	common.BooleanValue is_folder = 3;
	common.ObjectReference impl = 4;
}

message SymLinkTargetReplyBody {
	FS fs = 1;
	file.File file = 2;
}

// --- ReadonlyFS.watchFolder ---
// Its an observable call, and initial request is PathOnlyRequestBody
// Observer expects FSEventMsg in next.

message FSEventMsg {
	string type = 1;
	string path = 2;
	common.StringValue src = 3;
	common.UInt64Value new_version = 4;
	common.StringValue name = 5;
	common.StringValue old_name = 6;
	common.StringValue new_name = 7;
	ListingEntryMsg entry = 8;
	common.UInt64Value move_label = 9;
	common.UInt64Value removed_arch_ver = 10;
	common.UInt64Value archived_version = 11;
}

// --- ReadonlyFS.watchFile ---
// Its an observable call, and initial request is PathOnlyRequestBody
// Observer expects FSEventMsg in next.

// --- ReadonlyFS.watchTree ---
// Its an observable call, and initial request is PathOnlyRequestBody
// Observer expects FSEventMsg in next.
message WatchTreeRequestBody {
	string path = 1;
	common.UInt32Value depth = 2;
}

// --- ReadonlyFS.close ---
// Request body is empty
// Reply body is empty

// --- ReadonlyFS.readonlySubRoot ---
// Request body is PathOnlyRequestBody
// Reply body is FS

// --- ReadonlyFS.listFolder ---
// Request body is PathOnlyRequestBody
message ListFolderReplyBody {
	repeated ListingEntryMsg entries = 1;
}

message ListingEntryMsg {
	string name = 1;
	common.BooleanValue is_file = 2;
	common.BooleanValue is_folder = 3;
	common.BooleanValue is_link = 4;
}

// --- ReadonlyFS.readJSONFile ---
// Request body is PathOnlyRequestBody
// Reply body contains utf8 bytes of a json string

// --- ReadonlyFS.readTxtFile ---
// Request body is PathOnlyRequestBody
// Reply body contains utf8 bytes of a string

// --- ReadonlyFS.readBytes ---
// Reply body is file.ReadBytesReplyBody
message ReadBytesRequestBody {
	string path = 1;
	common.UInt64Value start = 2;
	common.UInt64Value end = 3;
}

// --- ReadonlyFS.getByteSource ---
// Request body is PathOnlyRequestBody
// Reply body is common.ObjectReference to bytes.FileByteSource.

// --- ReadonlyFS.readonlyFile ---
// Request body is PathOnlyRequestBody
// Reply body is file.File

// --- ReadonlyFS.select ---
// Its an observable call.
// First and only interim reply body is a common.ObjectReference to
// FSCollection. Call completion indicates the end of a search process
message SelectRequestBody {
	message SelectCriteria {
		common.StringValue exact_name = 1;
		common.StringValue pattern = 2;
		common.StringValue regexp = 3;
		common.UInt32Value depth = 4;
		repeated string type = 5;
		string action = 6;
	}
	string path = 1;
	SelectCriteria criteria = 2;
}


// ==== FSCollection referable object ====

// --- FSCollection.get ---
message FSCGetRequestBody {
	string name = 1;
}
message FSCGetReplyBody {
	FSItem item = 1;
}

message FSItem {
	message Location {
		FS fs = 1;
		string path = 2;
		string storage_use = 3;
		string storage_type = 4;
	}
	message Item {
		FS fs = 1;
		file.File file = 2;
		// collection is a reference to FSCollection
		common.ObjectReference collection = 3;
	}

	common.BooleanValue is_file = 1;
	common.BooleanValue is_folder = 2;
	common.BooleanValue is_link = 3;
	common.BooleanValue is_collection = 4;
	Item item = 5;
	Location location = 6;
}

// --- FSCollection.getAll ---
// Request body is empty
message FSCGetAllReplyBody {
	repeated NameAndItem items = 1;
}

message NameAndItem {
	string name = 1;
	FSItem item = 2;
}

// --- FSCollection.entries ---
// Request body is empty
// Reply body is common.ObjectReference to iterator of IterResMsg

message IterResMsg {
	common.BooleanValue done = 1;
	NameAndItem value = 2;
}

// --- FSCollection.watch ---
// Its an observable call.
// Observer expects CollectionEvent in next.

message CollectionEvent {
	string type = 1;
	common.StringValue path = 2;
	FSItem item = 3;
}


// ==== ReadonlyFSVersionedAPI referable object ====

// --- ReadonlyFSVersionedAPI.stat ---
// Request body is PathAndFlagsRequestBody
// Reply body is file.StatsMsg

// --- ReadonlyFSVersionedAPI.getXAttr ---
message VersionedGetXAttrRequestBody {
	string path = 1;
	string xa_name = 2;
	file.VersionedReadFlags flags = 10;
}
// Reply body is file.VersionedGetXAttrReplyBody

message PathAndFlagsRequestBody {
	string path = 1;
	file.VersionedReadFlags flags = 2;
}

// --- ReadonlyFSVersionedAPI.listXAttrs ---
// Request body is PathAndFlagsRequestBody
// Reply body is file.VersionedListXAttrsReplyBody

// --- ReadonlyFSVersionedAPI.listFolder ---
// Request body is PathAndFlagsRequestBody
message VersionedListFolderReplyBody {
	uint64 version = 1;
	repeated ListingEntryMsg entries = 2;
}

// --- ReadonlyFSVersionedAPI.readJSONFile ---
// Request body is PathAndFlagsRequestBody
// Reply body is file.VersionedReadJsonReplyBody

// --- ReadonlyFSVersionedAPI.readTxtFile ---
// Request body is PathAndFlagsRequestBody
// Reply body is file.VersionedReadTxtReplyBody

// --- ReadonlyFSVersionedAPI.readBytes ---
message VersionedReadBytesRequestBody {
	string path = 1;
	common.UInt64Value start = 2;
	common.UInt64Value end = 3;
	file.VersionedReadFlags flags = 10;
}
// Reply body is file.VersionedReadBytesReplyBody

// --- ReadonlyFSVersionedAPI.getByteSource ---
// Request body is PathAndFlagsRequestBody
// Reply body is file.VersionedGetByteSourceReplyBody

// --- ReadonlyFSVersionedAPI.getByteSource ---
// Request body is PathAndFlagsRequestBody
// Reply body is file.ListVersionsReplyBody


// ==== WritableFS referable as impl object (extends ReadonlyFS) ====

// --- WritableFS.updateXAttrs ---
// Reply has only status and body is empty
message UpdateXAttrsRequestBody {
	string path = 1;
	file.XAttrsChanges changes = 2;
}

// --- WritableFS.makeFolder ---
// Reply has only status and body is empty
message MakeFolderRequestBody {
	string path = 1;
	common.BooleanValue exclusive = 2;
}

// --- WritableFS.deleteFolder ---
// Reply has only status and body is empty
message DeleteFolderRequestBody {
	string path = 1;
	common.BooleanValue remove_content = 2;
}

// --- WritableFS.deleteFile ---
// Request body is PathOnlyRequestBody
// Reply has only status and body is empty

// --- WritableFS.move ---
// Reply has only status and body is empty
message MoveRequestBody {
	string src = 1;
	string dst = 2;
}

// --- WritableFS.copyFile ---
// Reply has only status and body is empty
message CopyFileRequestBody {
	string src = 1;
	string dst = 2;
	common.BooleanValue overwrite = 3;
}

// --- WritableFS.copyFolder ---
// Reply has only status and body is empty
message CopyFolderRequestBody {
	string src = 1;
	string dst = 2;
	common.BooleanValue merge_and_overwrite = 3;
}

// --- WritableFS.saveFile ---
// Reply has only status and body is empty
message SaveFileRequestBody {
	// file is a reference to File impl object
	common.ObjectReference file = 1;
	string dst = 2;
	common.BooleanValue overwrite = 3;
}

// --- WritableFS.saveFolder ---
// Reply has only status and body is empty
message SaveFolderRequestBody {
	// file is a reference to FS impl object
	common.ObjectReference folder = 1;
	string dst = 2;
	common.BooleanValue merge_and_overwrite = 3;
}

// --- WritableFS.deleteLink ---
// Request body is PathOnlyRequestBody
// Reply has only status and body is empty

// --- WritableFS.link ---
// Reply has only status and body is empty
message LinkRequestBody {
	string path = 1;
	// target is a reference to either FS or File impl object
	common.ObjectReference target = 2;
}

// --- WritableFS.writableSubRoot ---
// Request body is PathAndOptFileFlags
// Reply body is FS

message PathAndOptFileFlags {
	string path = 1;
	FileFlags flags = 2;
}

message FileFlags {
	common.BooleanValue truncate = 1;
	common.BooleanValue create = 2;
	common.BooleanValue exclusive = 3;
}

// --- WritableFS.writeJSONFile ---
// Reply has only status and body is empty
message WriteJsonFileRequestBody {
	string path = 1;
	string json = 2;
	FileFlags flags = 3;
}

// --- WritableFS.writeTxtFile ---
// Reply has only status and body is empty
message WriteTxtFileRequestBody {
	string path = 1;
	string txt = 2;
	FileFlags flags = 3;
}

// --- WritableFS.writeBytes ---
// Reply has only status and body is empty
message WriteBytesRequestBody {
	string path = 1;
	bytes bytes = 2;
	FileFlags flags = 3;
}

// --- WritableFS.getByteSink ---
// Request body is PathAndOptFileFlags
// Reply body is common.ObjectReference to bytes.FileByteSink

// --- WritableFS.writableFile ---
// Request body is PathAndOptFileFlags
// Reply body is file.File


// ==== WritableFSVersionedAPI referable object
//                                      (extends ReadonlyFSVersionedAPI) ====

// --- WritableFSVersionedAPI.updateXAttrs ---
// Request body is UpdateXAttrsRequestBody
// Reply body is common.UInt64Value

// --- WritableFSVersionedAPI.writeJSONFile ---
// Reply body is common.UInt64Value
message VersionedWriteJsonFileRequestBody {
	string path = 1;
	string json = 2;
	VersionedFileWriteFlags flags = 3;
}

message VersionedFileWriteFlags {
	common.BooleanValue truncate = 1;
	common.BooleanValue create = 2;
	common.BooleanValue exclusive = 3;
	common.UInt64Value current_version = 10;
}

// --- WritableFSVersionedAPI.writeTxtFile ---
// Reply body is common.UInt64Value
message VersionedWriteTxtFileRequestBody {
	string path = 1;
	string txt = 2;
	VersionedFileWriteFlags flags = 3;
}

// --- WritableFSVersionedAPI.writeBytes ---
// Reply body is common.UInt64Value
message VersionedWriteBytesRequestBody {
	string path = 1;
	bytes bytes = 2;
	VersionedFileWriteFlags flags = 3;
}

// --- WritableFSVersionedAPI.getByteSink ---
// Reply body is file.VersionedGetByteSinkReplyBody
message VersionedGetByteSinkRequestBody {
	string path = 1;
	VersionedFileWriteFlags flags = 2;
}

// --- WritableFSVersionedAPI.archiveCurrent ---
// Reply body is common.UInt64Value
message ArchiveCurrentRequestBody {
	string path = 1;
	common.UInt64Value version = 2;
}


// ==== ReadonlyFSSyncAPI referable object ====

// --- ReadonlyFSSyncAPI.status ---
// Reply body is file.SyncStatusMsg
message FSSyncStatusRequestBody {
	string path = 1;
	bool skip_server_check = 2;
}

// --- ReadonlyFSSyncAPI.isRemoteVersionOnDisk ---
message FSSyncIsOnDiskRequestBody {
	string path = 1;
	uint64 version = 2;
}
message FSSyncIsOnDiskReplyBody {
	string status = 1;
}

// --- ReadonlyFSSyncAPI.download ---
// Reply has only status and body is empty
message FSSyncDownloadRequestBody {
	string path = 1;
	uint64 version = 2;
}

// --- ReadonlyFSSyncAPI.adoptRemote ---
// Reply has only status and body is empty
message AdoptRemoteRequestBody {
	string path = 1;
	file.OptionsToAdopteRemote opts = 2;
}

// --- ReadonlyFSSyncAPI.diffCurrentAndRemote ---
message DiffCurrentAndRemoteRequestBody {
	string path = 1;
	common.UInt64Value remote_version = 2;
}
message DiffCurrentAndRemoteReplyBody {
	FolderDiff diff = 1;
}

message FolderDiff {
	message TimeStamps {
		uint64 current = 1;
		common.UInt64Value remote = 2;
	}
	message XAttrs {
		repeated file.NameAndXAttrValue in_current = 1;
		repeated file.NameAndXAttrValue in_remote = 2;
		repeated string name_overlaps = 3;
	}
	uint64 current_version = 1;
	common.UInt64Value remote_version = 2;
	repeated ListingEntryMsg in_current = 3;
	repeated ListingEntryMsg in_remote = 4;
	repeated string name_overlaps = 5;
	TimeStamps ctime = 6;
	TimeStamps mtime = 7;
	XAttrs xattrs = 8;
}


// ==== WritableFSSyncAPI referable object ====

// --- WritableFSSyncAPI.upload ---
// Reply body is common.UInt64Value
message FSSyncUploadRequestBody {
	string path = 1;
	file.OptionsToUploadLocal opts = 2;
}
message FSSyncUploadReplyBody {
	common.UInt64Value uploaded_version = 1;
}

// --- WritableFSSyncAPI.adoptRemoteFolderItem ---
message AdoptRemoteFolderItemRequestBody {
	message Options {
		common.UInt64Value local_version = 1;
		common.UInt64Value upload_version = 2;
	}
	string path = 1;
	string item_name = 2;
	Options opts = 3;
}
