module ViewModel::ActiveRecord::Controller

def create(serialize_context: new_serialize_context, deserialize_context: new_deserialize_context)

def create(serialize_context: new_serialize_context, deserialize_context: new_deserialize_context)
  update_hash, refs = parse_viewmodel_updates
  view = nil
  pre_rendered = viewmodel_class.transaction do
    view = viewmodel_class.deserialize_from_view(update_hash, references: refs, deserialize_context: deserialize_context)
    ViewModel.preload_for_serialization(view)
    view = yield(view) if block_given?
    prerender_viewmodel(view, serialize_context: serialize_context)
  end
  render_json_string(pre_rendered)
  view
end

def destroy(serialize_context: new_serialize_context, deserialize_context: new_deserialize_context)

def destroy(serialize_context: new_serialize_context, deserialize_context: new_deserialize_context)
  viewmodel_ids = parse_param(
    :id, with: IknowParams::Serializer::ArrayOf.new(ViewmodelIdSerializer, allow_singleton: true))
  viewmodel_class.transaction do
    views = viewmodel_class.find(viewmodel_ids, eager_include: false)
    views.each do |view|
      view.destroy!(deserialize_context: deserialize_context)
    end
  end
  render_viewmodel(nil)
end

def index(scope: nil, viewmodel_class: self.viewmodel_class, serialize_context: new_serialize_context(viewmodel_class: viewmodel_class))

def index(scope: nil, viewmodel_class: self.viewmodel_class, serialize_context: new_serialize_context(viewmodel_class: viewmodel_class))
  views = nil
  pre_rendered = viewmodel_class.transaction do
    views = viewmodel_class.load(scope: scope)
    views = yield(views) if block_given?
    prerender_viewmodel(views, serialize_context: serialize_context)
  end
  render_json_string(pre_rendered)
  views
end

def migrated_deep_schema_version

def migrated_deep_schema_version
  ViewModel::Migrator.migrated_deep_schema_version(viewmodel_class, migration_versions, include_referenced: true)
end

def parse_viewmodel_updates

def parse_viewmodel_updates
  super.tap do |update_hash, refs|
    if migration_versions.present?
      migrator = ViewModel::UpMigrator.new(migration_versions)
      migrator.migrate!({ 'data' => update_hash, 'references' => refs })
    end
  end
end

def prerender_viewmodel(...)

def prerender_viewmodel(...)
  super do |jbuilder|
    yield(jbuilder) if block_given?
    # migrate the resulting structure before it's serialized to a json string
    if migration_versions.present?
      tree = jbuilder.attributes!
      migrator = ViewModel::DownMigrator.new(migration_versions)
      migrator.migrate!(tree)
    end
  end
end

def show(scope: nil, viewmodel_class: self.viewmodel_class, serialize_context: new_serialize_context(viewmodel_class: viewmodel_class))

def show(scope: nil, viewmodel_class: self.viewmodel_class, serialize_context: new_serialize_context(viewmodel_class: viewmodel_class))
  view = nil
  pre_rendered = viewmodel_class.transaction do
    view = viewmodel_class.find(viewmodel_id, scope: scope)
    view = yield(view) if block_given?
    prerender_viewmodel(view, serialize_context: serialize_context)
  end
  render_json_string(pre_rendered)
  view
end

def viewmodel_id

def viewmodel_id
  parse_param(:id, with: ViewmodelIdSerializer)
end