# The tasks class provides an interface to call tasks on
# the backend server.
class Tasks
  def initialize(page)
    @page = page
    @callback_id = 0
    @callbacks = {}
    
    page.channel.on('message') do |_, *args|
      received_message(*args)
    end
  end
  
  def call(class_name, method_name, *args, &callback)
    if callback
      callback_id = @callback_id
      @callback_id += 1

      # Track the callback
      # TODO: Timeout on these callbacks
      @callbacks[callback_id] = callback
    else
      callback_id = nil
    end
    
    @page.channel.send_message([callback_id, class_name, method_name, *args])
  end
  
  
  def received_message(name, callback_id, *args)
    case name
    when 'response'
      response(callback_id, *args)
    when 'changed'
      changed(*args)
    when 'added'
      added(*args)
    when 'removed'
      removed(*args)
    when 'reload'
      reload
    end
  end
  
  def response(callback_id, result, error)
    callback = @callbacks.delete(callback_id)
    
    if callback
      if error
        # TODO: full error handling
        puts "Error: #{error.inspect}"
      else
        callback.call(result)
      end
    end
  end
  
  def changed(model_id, data)
    $loading_models = true
    puts "From Backend: UPDATE: #{model_id} with #{data.inspect}"
    Persistors::ModelStore.update(model_id, data)
    $loading_models = false
  end
  
  def added(path, data)
    $loading_models = true
    
    # Don't add if already in there
    # TODO: shouldn't send twice
    unless Persistors::ModelStore.from_id(data[:_id])
    
      _, parent_id = data.find {|k,v| k != :_id && k[-3..-1] == '_id'}
      if parent_id
        parent_collection = Persistors::ModelStore.from_id(parent_id).model
      else
        # On the root
        parent_collection = $page.store
      end
    
      puts "From Backend: Add: #{path.inspect} - #{data.inspect}"
      parent_collection.send(path) << data
    end
    $loading_models = false
  end
  
  def removed(id)
    puts "From Backend: Remove: #{id}"
    $loading_models = true
    model = Persistors::ModelStore.from_id(id)
    model.delete!
    $loading_models = false
  end
  
  def reload
    puts "RELOAD"
    # Stash the current page value
    value = JSON.dump($page.page.cur.to_h.reject {|k,v| v.reactive? })
    
    # If this browser supports session storage, store the page, so it will
    # be in the same state when we reload.
    if `sessionStorage`
      `sessionStorage.setItem('___page', value);`
    end
    
    $page.page._reloading = true
    `window.location.reload(false);`
  end
end