<?php

final class SemiStructuredObjectInstanceEditEngine
  extends PhabricatorEditEngine {

  const ENGINECONST = 'sst:objectinstance';

  private $objectType;

  public function isEngineConfigurable() {
    return false;
  }

  public function getEngineName() {
    return pht('Object Instance');
  }

  public function getSummaryHeader() {
    return pht('Edit Object Instance');
  }

  public function getSummaryText() {
    return pht('This engine is used to modify object instances.');
  }

  public function getEngineApplicationClass() {
    return 'SemiStructuredDataApplication';
  }

  public function setObjectType(SemiStructuredObjectType $object_type) {
    $this->objectType = $object_type;
    return $this;
  }

  protected function newEditableObject() {
    $viewer = $this->getViewer();
    return SemiStructuredObjectInstance::initializeNewObjectInstance(
        $viewer,
        $this->objectType);
  }

  protected function newObjectQuery() {
    return new SemiStructuredObjectInstanceQuery();
  }

  protected function getObjectCreateTitleText($object) {
    return pht('Create Object Instance');
  }

  protected function getObjectCreateButtonText($object) {
    return pht('Create Object Instance');
  }

  protected function getObjectCreateCancelURI($object) {
    // TODO if objjec has link to class - go to that class
    return '/semistructured/';
  }

  protected function getEditorURI() {
    return $this->getApplication()->getApplicationURI('editinstance/');
  }

  public function getCreateURI($form_key) {

    if ($this->objectType) {
      return $this->getApplication()->getApplicationURI(
        "type/{$this->objectType->getID()}/new/");
    }

    return null;
  }

  protected function getObjectEditTitleText($object) {
    return pht('Edit Object: %d', $object->getID());
  }

  protected function getObjectEditShortText($object) {
    return pht('Edit Object');
  }

  protected function getObjectCreateShortText() {
    return pht('Create Object Instance');
  }

  protected function getObjectName() {
    return pht('Object Instance');
  }

  protected function getObjectViewURI($object) {
    return $object->getURI();
  }

  protected function buildCustomEditFields($object) {

    $fields = array(
      id(new PhabricatorTextEditField())
        ->setKey('classPHID')
        ->setLabel(pht('Object Type'))
        ->setDescription(pht('Type of the object.'))
        ->setConduitDescription(pht('Set type of object.'))
        ->setIsHidden(true)
        ->setTransactionType(
          SemiStructuredObjectInstanceClassTransaction::TRANSACTIONTYPE)
        ->setIsRequired(true)
        ->setValue($object->getClassPHID()),
      id(new PhabricatorTextEditField())
        ->setKey('name')
        ->setLabel(pht('Name'))
        ->setDescription(pht('Name of the object.'))
        ->setConduitDescription(pht('Rename the object.'))
        ->setConduitTypeDescription(pht('New object name.'))
        ->setTransactionType(
          SemiStructuredObjectInstanceNameTransaction::TRANSACTIONTYPE)
        ->setValue($object->getName()),
      id(new PhabricatorRemarkupEditField())
        ->setKey('description')
        ->setLabel(pht('Free text'))
        ->setDescription(pht('Object instance free text (Remarkup).'))
        ->setConduitTypeDescription(pht('New object free type.'))
        ->setTransactionType(
          SemiStructuredObjectInstanceDescriptionTransaction::TRANSACTIONTYPE)
        ->setValue($object->getDescription()),

      id(new PhabricatorTextAreaEditField())
        ->setKey('rawdata')
        ->setLabel(pht('Structured content'))
        ->setDescription(pht('Object structured data (JSON).'))
        ->setConduitTypeDescription(
            pht('Object body (JSON, but as a String!).'))
        ->setMonospaced(true)
        ->setIsRequired(true)
        ->setTransactionType(
          SemiStructuredObjectInstanceRawDataTransaction::TRANSACTIONTYPE)
        ->setValue($object->getRawData()),
    );

    if ($this->objectType) {
      array_unshift(
        $fields,
        (new PhabricatorStaticEditField())
          ->setKey('objecttype')
          ->setLabel(pht('Object Type'))
          ->setValue($this->objectType->getName()));
    }

    return $fields;
  }


  // Put the raw-data field at the bottom of the form
  protected function willConfigureFields($object, array $fields) {
    $config = $this->getEditEngineConfiguration();

    $order = array_keys($fields);
    $json_index = array_search('rawdata', $order);

    if ($json_index !== false) {
      unset($order[$json_index]);
      $order[] = 'rawdata';

      $config->setFieldOrder($order);
    }

    return $fields;
  }


}
