<?php

namespace FSVendor\WPDesk\ABTesting\ABTest;

use FSVendor\WPDesk\ABTesting\ABTest;
use FSVendor\WPDesk\Persistence\ElementNotExistsException;
use FSVendor\WPDesk\Persistence\PersistentContainer;
/**
 * Base class for AB tests with equal groups generated by random number generator
 *
 * @package WPDesk\ABTesting\ABTest
 */
abstract class EqualGroupsRandomABTest implements ABTest
{
    const CONTAINER_VALUE_PREFIX = 'ab_test';
    /**
     * Used to save info about generated variant
     *
     * @var PersistentContainer
     */
    private $container;
    /**
     * How many groups/variants are in the whole test
     *
     * @var int
     */
    private $variant_count;
    /**
     * Some unique test name for persitence pusposes and for higher readability
     *
     * @var string
     */
    private $test_name;
    /**
     * Derived classes can use this value to know what variant id is generated
     *
     * @var int
     */
    protected $current_variant_id;
    /**
     * @param int                 $variant_count Number of equal size groups to generate.
     * @param string              $test_name     Specific test name. Should be unique. Used to persist.
     * @param PersistentContainer $container     Container to persist data.
     */
    public function __construct($variant_count, $test_name, PersistentContainer $container)
    {
        assert(is_int($variant_count) && $variant_count > 0, '$variant_count makes no sense');
        $this->variant_count = $variant_count;
        $this->test_name = $test_name;
        $this->container = $container;
        $this->initialize_variant_id();
    }
    /**
     * Clears info about variant and draws again
     */
    public function reset()
    {
        $this->container->set($this->get_container_key(), null);
        $this->initialize_variant_id();
    }
    /**
     * @return void
     */
    private function initialize_variant_id()
    {
        $variant_id = $this->get_variant_id_from_container();
        if ($variant_id === null) {
            $variant_id = $this->generate_variant_id();
            $this->container->set($this->get_container_key(), $variant_id);
        }
        $this->current_variant_id = $variant_id;
    }
    /**
     * Returns variant id if exists.
     *
     * @return int|null Returns null if not exists.
     */
    private function get_variant_id_from_container()
    {
        try {
            $variant_id = $this->container->get($this->get_container_key());
            return (int) $variant_id;
        } catch (ElementNotExistsException $e) {
            return null;
        }
    }
    /**
     * Key for where variant id should be saved in the persistence container
     *
     * @return string
     */
    protected function get_container_key()
    {
        return implode('_', [self::CONTAINER_VALUE_PREFIX, $this->test_name, 'variant_id']);
    }
    /**
     * @return int
     */
    private function generate_variant_id()
    {
        return mt_rand(1, $this->variant_count);
    }
}
