     owner = @getOwner(event.currentTarget)
     @doMoveComponent operation.component, owner,
       operation.sourceController.getContainer operation.sourceOwner
-
-  # Override this to set other properties on move; but ideally don't, if
-  # possible, that should be done in the container class instead
-  doMoveComponent: (component, owner, oldContainer, count = 1) ->
-    if component instanceof CBGA.Component
-      if count is 1
-        component.moveTo @getContainer owner
-      else
-        type = @rules.getComponentType component.type
-        selector = type: component.type
-        if type.stackProperty?
-          selector[type.stackProperty] = component[type.stackProperty]
-        component.container().find selector, limit: count
-        .forEach (eachComponent) =>
-          eachComponent.moveTo @getContainer owner
-
-    else if component instanceof ui.ComponentStack
-      type = @rules.getComponentType component.type
-      selector = type: component.type
-      if type.stackProperty?
-        selector[type.stackProperty] = component[type.stackProperty]
-      component.container().find selector, limit: count
-      .forEach (eachComponent) =>
-        eachComponent.moveTo @getContainer owner
-
-    else if component.provider
-      # This can't be done on the client because typically a provider is private
-      # (deck of cards, for example)
-      # XXX missing stackProperty
-      target = @getContainer owner
-      options =
-        rules: @rules.name
-        type: component.type
-        source: component.container._id
-        target: target._id
-        count: count
-      Meteor.call 'component.draw', options
+    true
+
+
+# XXX there's an API mismatch since a PanelContainerController is bound to a
+# panel and shared between containers, while a ComponentController is bound to
+# a specific component. Have to evaluate if it's a problem.
+class ui.ComponentController extends ui.Controller
+  constructor: ({@uiType, @component} = {}) ->
+    @rules = CBGA.getGameRules @component.game().rules
+
+  # We'll probably need something like renderFull for recursive-ish components
+  # (e.g. cards that go on cards)
+  renderCounters: ->
+    new Blaze.Template =>
+      if @uiType.contains.length
+        _.map @uiType.contains, (typeName) =>
+          type = @rules.getComponentType typeName
+          if type.isCounter
+            type.renderCounter @component
+
+  handleDragOver: (event) ->
+    operation = ui.DragAndDropService.get event
+    return unless operation
+    return if operation.sourceOwner._id is @component._id and operation.sourceController is @
+    if operation.component.type in @uiType.contains
+      $(event.currentTarget).addClass 'drag-allowed'
+      event.preventDefault()
+      true
+
+  handleDrop: (event) ->
+    $(event.currentTarget).removeClass 'drag-allowed'
+    operation = ui.DragAndDropService.get event
+    return unless operation
+    event.preventDefault()
+    event.stopImmediatePropagation()
+    console.log 'drop', operation
+    @doMoveComponent operation.component, @component,
+      operation.sourceController.getContainer operation.sourceOwner
+    true
 
 
 class ui.DragAndDropOperation



class ui.Controller extends EventEmitter
  # does nothing for now, but can be used for instanceof


class ui.PanelContainerController extends ui.Controller



# Slots are really later on in the backlog, but here's the API anyway
# Slots are for cases where exactly zero or one component of certain
# characteristics can be played. For example, in Girls War, the current
# trends have one slot for the positive trend, and one for the negative.
# The units *may* be implemented with a slot for the manager.
class ui.Slot
  constructor: ({@id, @title, @panel} = {}) ->
    check @id, String
