<?php

namespace Ignite\Core\Models\Source;

use Exception;
use Ignite\Core\Contracts\Source;

class Manager
{
    /**
     * @var array
     */
    protected $sources;

    /**
     * Manager instance.
     *
     * @param array $sources
     */
    public function __construct(array $sources)
    {
        $this->sources = $sources;
    }

    /**
     * Register a source model.
     *
     * @param string $key
     * @param string $class
     *
     * @return self
     */
    public function register($key, $class)
    {
        $this->sources[$key] = $class;

        return $this;
    }

    /**
     * Interpolate the given value to derive the correct source model.
     *
     * @param array|string $value
     *
     * @return array|Source
     * @throws Exception
     */
    public function interpolate($value)
    {
        // When the value is an array, we don't need to interpolate it, just send it back.
        if (is_array($value)) {
            return $value;
        }

        $value = trim($value);

        // When the value is a comma or pipe-delimited string, split it and return it.
        if (! preg_match('/^{([0-9a-zA-Z_]+)}$/', $value)) {
            $split = preg_split("/[|,\n]/", $value, -1, PREG_SPLIT_NO_EMPTY);

            if (! is_array($split)) {
                return [$split];
            }

            return $split;
        }

        // Otherwise, we should interpolate it.
        $key = str_replace(['{', '}'], '', $value);

        return $this->toDropdown($key);
    }

    /**
     * Make a source model instance from the given key.
     *
     * @param string $key
     *
     * @return Source
     * @throws Exception
     */
    public function make($key)
    {
        if (! isset($this->sources[$key])) {
            throw new Exception(
                "Unknown data source `{$key}`. Please check the core.php config file for a matching source model."
            );
        }

        return app($this->sources[$key]);
    }

    /**
     * Get the dropdown array for the source model of the given key.
     *
     * @param string $key
     *
     * @return array
     * @throws Exception
     */
    public function toDropdown($key)
    {
        return $this->make($key)->toDropdown();
    }
}