<?php

class Cornerstone_Model_Option extends Cornerstone_Plugin_Component {

  public $name = 'option';

  // Lookup an option, and persist defaults if it doesn't exist
  // This lets us populate defaults single time, meaning IDs can be unique but consistent
  public function lookup( $option ) {
    $stored = get_option( $option );
    if ($stored === false ) {
      $stored = apply_filters( "cornerstone_option_model_save_$option", apply_filters( "cornerstone_option_model_defaults_$option", null ) );
      update_option( $option, $stored );
    }
    return apply_filters( "cornerstone_option_model_load_$option", $stored );
  }

  public function query( $params = array() ) {

    // Find All
    if ( empty( $params ) || ! isset( $params['query'] ) || ! isset( $params['query']['id'] ) ) {
      return false;
    }

    $this->validate( $params['query']['id'], 'access' );
    $option = $params['query']['id'];

    return array(
      'data' => array(
        'id' => $params['query']['id'],
        'type' => 'option',
        'attributes' => array(
          'value' => $this->lookup( $option )
        )
      ),
      'meta' => array( 'request_params' => $params, 'ID' => $params['query']['id'] )
    );
  }

  protected function validate( $id, $operation = '' ) {

    $allowed = apply_filters( 'cornerstone_option_model_whitelist', array( '' ) );

    if ( ! in_array( $id, $allowed, true ) ) {
      throw new Exception( "Attempted to $operation option outside of whitelist: $id" );
    }

    if ( ! apply_filters( "cornerstone_option_model_permissions_$id", 'access' === $operation, $operation ) ) {
      throw new Exception( "Unauthorized: $id | $operation" );
    }

  }

  public function update( $params ) {

    $atts = $this->atts_from_request( $params );

    if ( ! $atts['id'] ) {
      throw new Exception( 'Attempting to update option without specifying a name.' );
    }

    $option = $atts['id'];
    $this->validate( $option, 'update' );

    update_option( $option, apply_filters( "cornerstone_option_model_save_$option", $atts['value'] ) );

    // Call after options is updated
    do_action( "cornerstone_after_option_save_$option", $atts );

    return array(
      'data' => array(
        'id' => $option,
        'type' => $this->name,
        'attributes' => array(
          'value' => apply_filters( "cornerstone_option_model_load_$option", get_option( $option ) )
        )
      )
    );
  }

  public function delete( $params ) {

    $atts = $this->atts_from_request( $params );

    if ( ! $atts['id'] ) {
      throw new Exception( 'Attempting to delete option without specifying a name.' );
    }

    $this->validate( $atts['id'], 'delete' );

    delete_option( $atts['id'] );

    return array(
      'data' => array(
        'id' => $atts['id'],
        'type' => $this->name
      )
    );
  }

  protected function atts_from_request( $params ) {

    if ( ! isset( $params['model'] ) || ! isset( $params['model']['data'] ) || ! isset( $params['model']['data']['attributes'] ) ) {
      throw new Exception( 'Request to Option model missing attributes.' );
    }

    $atts = $params['model']['data']['attributes'];

    if ( isset( $params['model']['data']['id'] ) ) {
      $atts['id'] = $params['model']['data']['id'];
    }

    return $atts;
  }

}
