module Coupdoeil::Params

def convert_to_global_id_hash(param)

def convert_to_global_id_hash(param)
  { GLOBAL_ID_KEY => param.to_global_id.to_s }
rescue URI::GID::MissingModelIdError
  raise SerializationError, "Unable to serialize #{param.class} " \
    "without an id. (Maybe you forgot to call save?)"
end

def deserialize(params)

def deserialize(params)
  Array.wrap(params).map { |param| deserialize_param(param) }
rescue StandardError
  raise DeserializationError
end

def deserialize_global_id(hash) = GlobalID::Locator.locate(hash[GLOBAL_ID_KEY])

def deserialize_global_id(hash) = GlobalID::Locator.locate(hash[GLOBAL_ID_KEY])

def deserialize_hash(serialized_hash) = serialized_hash.transform_values { deserialize_param(_1) }

def deserialize_hash(serialized_hash) = serialized_hash.transform_values { deserialize_param(_1) }

def deserialize_param(param)

def deserialize_param(param)
  case param
  when Array
    param.map { |arg| deserialize_param(arg) }
  when Hash
    if serialized_global_id?(param)
      deserialize_global_id(param)
    else
      deserialize_hash(param)
    end
  else
    param
  end
end

def serialize(*params)

def serialize(*params)
  ActiveSupport::Notifications.instrument("serialize_popover_params.coupdoeil") do
    params.map { |param| serialize_param(param) }
  end
end

def serialize_hash(param)

def serialize_hash(param)
  param.each_with_object({}) do |(key, value), hash|
    hash[serialize_hash_key(key)] = serialize_param(value)
  end
end

def serialize_hash_key(key)

def serialize_hash_key(key)
  case key
  when *RESERVED_KEYS
    raise SerializationError, "Can't serialize a Hash with reserved key #{key.inspect}"
  when String, Symbol
    key.to_s
  else
    raise SerializationError, "Only string and symbol hash keys may be serialized as popover params, but #{key.inspect} is a #{key.class}"
  end
end

def serialize_param(param)

def serialize_param(param)
  case param
  when GlobalID::Identification
    convert_to_global_id_hash(param)
  when Array
    param.map { serialize_param(_1) }
  when Hash
    serialize_hash(param)
  else
    param
  end
end

def serialized_global_id?(hash) = hash.size == 1 && hash.include?(GLOBAL_ID_KEY)

def serialized_global_id?(hash) = hash.size == 1 && hash.include?(GLOBAL_ID_KEY)