// NewViewModel returns a new ViewModel instance.
func NewViewModel() *ViewModel {
	vm := &ViewModel{}

	vm.projects = viewmodel.NewValueSelectionNode("Select", nil, "")
	vm.newProjectID = viewmodel.NewEditableStringValueNode("New Project Name", "")
	vm.createProject = viewmodel.NewActionNode("Create Project")
	vm.textureCount = viewmodel.NewStringValueNode("Texture Count", "")
	projectSection := viewmodel.NewSectionNode("Project",
		[]viewmodel.Node{vm.projects, vm.newProjectID, vm.createProject, vm.textureCount},
		viewmodel.NewBoolValueNode("Available", true))

	vm.levels = viewmodel.NewValueSelectionNode("Level", nil, "")
	vm.levelIsRealWorld = viewmodel.NewBoolValueNode("Is Real World", false)
	vm.tiles = NewTilesViewModel(vm.levelIsRealWorld)
	vm.levelObjects = NewObjectsViewModel(vm.levelIsRealWorld)

	vm.levelTextureIndex = viewmodel.NewValueSelectionNode("Texture Index", []string{""}, "")
	vm.levelTextureID = viewmodel.NewValueSelectionNode("Texture ID", []string{""}, "")
	levelTexturesControlSection := viewmodel.NewSectionNode("Level Textures",
		[]viewmodel.Node{vm.levelTextureIndex, vm.levelTextureID}, vm.levelIsRealWorld)
	mapControlSection := viewmodel.NewSectionNode("Control", []viewmodel.Node{vm.levels}, viewmodel.NewBoolValueNode("", true))
	mapSectionSelection := viewmodel.NewSectionSelectionNode("Map Section", map[string]*viewmodel.SectionNode{
		"Control":        mapControlSection,
		"Level Textures": levelTexturesControlSection,
		"Tiles":          vm.tiles.root,
		"Objects":        vm.levelObjects.root}, "Control")

	projectSelected := viewmodel.NewBoolValueNode("Available", false)
	vm.projects.Selected().Subscribe(func(projectID string) {
		projectSelected.Set(projectID != "")
	})
	mapSection := viewmodel.NewSectionNode("Map", []viewmodel.Node{mapSectionSelection}, projectSelected)

	vm.mainSection = viewmodel.NewSectionSelectionNode("Section", map[string]*viewmodel.SectionNode{
		"Project": projectSection,
		"Map":     mapSection}, "Project")

	vm.pointerCoordinate = viewmodel.NewStringValueNode("Pointer at", "")

	vm.root = viewmodel.NewSectionNode("",
		[]viewmodel.Node{vm.mainSection, vm.pointerCoordinate},
		viewmodel.NewBoolValueNode("", true))

	return vm
}
// NewObjectsViewModel returns a new instance of a ObjectsViewModel.
func NewObjectsViewModel(levelIsRealWorld *viewmodel.BoolValueNode) *ObjectsViewModel {
	vm := &ObjectsViewModel{}

	vm.selectedObject = viewmodel.NewValueSelectionNode("Selected Object", []string{""}, "")
	vm.cst = viewmodel.NewStringValueNode("C/S/T", "")

	vm.root = viewmodel.NewSectionNode("Objects",
		[]viewmodel.Node{vm.selectedObject, vm.cst},
		viewmodel.NewBoolValueNode("", true))

	return vm
}
// NewTilesViewModel returns a new instance of a TilesViewModel.
func NewTilesViewModel(levelIsRealWorld *viewmodel.BoolValueNode) *TilesViewModel {
	vm := &TilesViewModel{}

	vm.tileType = viewmodel.NewValueSelectionNode("Tile Type", []string{string(model.Open), string(model.Solid),
		string(model.DiagonalOpenSouthEast), string(model.DiagonalOpenSouthWest), string(model.DiagonalOpenNorthWest), string(model.DiagonalOpenNorthEast),
		string(model.SlopeSouthToNorth), string(model.SlopeWestToEast), string(model.SlopeNorthToSouth), string(model.SlopeEastToWest),
		string(model.ValleySouthEastToNorthWest), string(model.ValleySouthWestToNorthEast), string(model.ValleyNorthWestToSouthEast), string(model.ValleyNorthEastToSouthWest),
		string(model.RidgeNorthWestToSouthEast), string(model.RidgeNorthEastToSouthWest), string(model.RidgeSouthEastToNorthWest), string(model.RidgeSouthWestToNorthEast),
		""},
		"")
	vm.floorHeight = viewmodel.NewValueSelectionNode("Floor Height Level", intStringList(0, 31), "")
	vm.ceilingHeight = viewmodel.NewValueSelectionNode("Ceiling Height Level", intStringList(1, 32), "")
	vm.slopeHeight = viewmodel.NewValueSelectionNode("Slope Height", intStringList(0, 31), "")
	vm.slopeControl = viewmodel.NewValueSelectionNode("Slope Control",
		[]string{model.SlopeCeilingInverted, model.SlopeCeilingMirrored, model.SlopeCeilingFlat, model.SlopeFloorFlat, ""},
		"")

	vm.floorTexture = viewmodel.NewValueSelectionNode("Floor Texture Index", []string{""}, "")
	vm.ceilingTexture = viewmodel.NewValueSelectionNode("Ceiling Texture Index", []string{""}, "")
	vm.wallTexture = viewmodel.NewValueSelectionNode("Wall Texture Index", []string{""}, "")

	vm.floorTextureRotations = viewmodel.NewValueSelectionNode("Floor Tex Rotations", intStringList(0, 3), "")
	vm.ceilingTextureRotations = viewmodel.NewValueSelectionNode("Ceiling Tex Rotations", intStringList(0, 3), "")
	vm.useAdjacentWallTexture = viewmodel.NewValueSelectionNode("Use Adj. Wall Tex", []string{"yes", "no", ""}, "")
	vm.wallTextureOffset = viewmodel.NewValueSelectionNode("Wall Texture Offset", intStringList(0, 31), "")

	realWorldSection := viewmodel.NewSectionNode("Real World",
		[]viewmodel.Node{vm.floorTexture, vm.ceilingTexture, vm.wallTexture,
			vm.floorTextureRotations, vm.ceilingTextureRotations,
			vm.useAdjacentWallTexture, vm.wallTextureOffset},
		levelIsRealWorld)

	vm.root = viewmodel.NewSectionNode("Tiles",
		[]viewmodel.Node{vm.tileType, vm.floorHeight, vm.ceilingHeight, vm.slopeHeight, vm.slopeControl,
			realWorldSection},
		viewmodel.NewBoolValueNode("", true))

	return vm
}