<?php

namespace Breakdance\Elements;

use function Breakdance\Render\getElementFromNodeType;

/**
 * @return string[]
 */
function get_element_classnames()
{
    $elementClassnames = array_filter(
        get_declared_classes(),
        function ($class) {
            if (is_subclass_of($class, 'Breakdance\Elements\Element')) {
                return true;
            }
        }
    );

    $cleanClassnames = array_values(
        array_map(
            function ($class) {
                return str_replace('Breakdance\\Elements\\', '', $class);
            },
            $elementClassnames
        )
    );

    return $cleanClassnames;
}

// TODO: mark all the functions that are duplicated in JS and PHP so we know to keep them in sync

/**
 * Mirrors to a JS function
 *
 * @param string $slug
 * @return string
 */
function getItemNameFromSlug($slug) {
    $parts = explode("\\", $slug);

    return $parts[1] ?? "";
}

/**
 * Mirrors to a JS function
 *
 * @param string $slug
 * @return string
 */
function getItemNamespaceFromSlug($slug) {
    $parts = explode("\\", $slug);

    return $parts[0] ?? "";
}

/**
 * See JS version for comments
 * @param string $type
 * @return string
 */
function autogenerateClassNameFromElementSlug($type)
{
    $name = strtolower(getItemNameFromSlug($type));
    $namespace = getItemNamespaceFromSlug($type);
    $uppercaseLettersFromNamespace = strtolower(preg_replace('/[a-z]/', '', $namespace));
    $classSuffix = $uppercaseLettersFromNamespace ?: substr($namespace, 0, 3);

    return "autogenerated-$classSuffix-$name";
}

/**
 * Mirrors to a JS function
 *
 * @param Element | string $element
 * @return string
 */
function getBaseClassNameForBuilderElement($element)
{
    /** @var Element $element */
    $element = $element;
    return $element::className() ?: autogenerateClassNameFromElementSlug($element::slug());
}

/**
 * Mirrors to a JS function
 *
 * @param string $node_type
 * @param string $node_id
 * @param int $post_id
 * @param int | null $repeater_item_node_id
 * @return string
 */
function getClassNameForNode(
    $node_type,
    $node_id,
    $post_id,
    $repeater_item_node_id = null
) {
    $className = getBaseClassNameForBuilderElement(getElementFromNodeType($node_type)) . "-" . $post_id . "-" . $node_id;
    if ($repeater_item_node_id !== null) {
        return $className . '-' . (string) $repeater_item_node_id;
    }
    return $className;
}



// used by element studio... all the others should be ditched

/**
 * @param string $slug
 * @param string $label
 * @param array $children
 * @param mixed $options
 * @param boolean $enable_media_queries
 * @param boolean $enable_hover
 * @param array $keywords
 * @return Control
 */
function c(
    $slug,
    $label,
    $children,
    $options,
    $enable_media_queries,
    $enable_hover,
    $keywords = []
) {
    return [
        'slug' => $slug,
        'label' => $label,
        'options' => $options,
        'enableMediaQueries' => $enable_media_queries,
        'enableHover' => $enable_hover,
        'children' => $children,
        'keywords' => $keywords,
    ];
}

/**
 * @param string $slug
 * @param string $label
 * @param array $children
 * @param mixed $options
 * @param string $type
 * @return Control
 */
function controlSection($slug, $label, $children = [], $options = null, $type = 'accordion')
{
    $options['type'] = 'section';

    /**
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress PossiblyNullArrayAccess
     */
    $options['sectionOptions']['type'] = $type;

    return array(
        'slug' => $slug,
        'label' => $label,
        'children' => $children,
        'options' => $options,
        'enableMediaQueries' => false,
        'enableHover' => false,
    );
}



/* slug can't have '-' character because it'll break Twig. we need to typecheck that */
/**
 * @param string $slug
 * @param string $label
 * @param mixed $options
 * @param boolean $enable_media_queries
 * @param array $children
 * @param array $keywords
 * @return Control
 */
function control(
    $slug,
    $label,
    $options,
    $enable_media_queries = false,
    $children = [],
    $keywords = []
) {
    return array(
        'slug' => $slug,
        'label' => $label,
        'children' => $children,
        'options' => $options,
        'enableMediaQueries' => $enable_media_queries,
        'enableHover' => false,
        'keywords' => $keywords,
    );
}

/* slug can't have '-' character because it'll break Twig. we need to typecheck that */
/**
 * @param string $slug
 * @param string $label
 * @param mixed $options
 * @param array $children
 * @param array $keywords
 * @return Control
 */
function responsiveControl($slug, $label, $options, $children = [], $keywords = [])
{
    return control($slug, $label, $options, true, $children, $keywords);
}

/**
 * @param string $slug
 * @param string $label
 * @param mixed $options
 * @param array $children
 * @param array $keywords
 * @return Control
 */
function responsiveControlWithHover($slug, $label, $options, $children = [], $keywords = [])
{
    $control = responsiveControl($slug, $label, $options, $children, $keywords);
    $control['enableHover'] = true;

    return $control;
}

/**
 * @param string $slug
 * @param string $label
 * @param array $children
 * @param mixed $options
 * @param boolean $enable_media_queries
 *
 * @return Control
 */
function repeaterControl(
    string $slug,
    string $label,
    $children = [],
    $options = null,
    bool $enable_media_queries = false
) {
    $options['type'] = 'repeater';
    $options['layout'] = 'vertical';

    return control($slug, $label, $options, $enable_media_queries, $children);
}

/**
 * @param string $slug
 * @param string $label
 * @param array $children
 * @param mixed $options
 * @param boolean $enable_media_queries
 *
 * @return Control
 */
function inlineRepeaterControl(
    string $slug,
    string $label,
    $children = [],
    $options = null,
    bool $enable_media_queries = false
) {
    $options['type'] = 'inline_repeater';
    $options['layout'] = 'vertical';

    return control($slug, $label, $options, $enable_media_queries, $children);
}

/**
 * TODO these can be removed when all elements using them are created with Element Studio
 * Element studio space bars are much better because the propertyPath is dynamic
 */

/**
 * @return array{location:string,cssProperty:string,affectedPropertyPath:string}[]
 */
function getSpaceAllSpacingBars()
{
    return [
        [
            'location' => 'inside-top',
            'cssProperty' => "padding-top",
            'affectedPropertyPath' => "design.spacing.padding.%%BREAKPOINT%%.top",
        ],
        [
            'location' => 'inside-right',
            'cssProperty' => "padding-right",
            'affectedPropertyPath' => "design.spacing.padding.%%BREAKPOINT%%.right",
        ],
        [
            'location' => 'inside-bottom',
            'cssProperty' => "padding-bottom",
            'affectedPropertyPath' => "design.spacing.padding.%%BREAKPOINT%%.bottom",
        ],
        [
            'location' => 'inside-left',
            'cssProperty' => "padding-left",
            'affectedPropertyPath' => "design.spacing.padding.%%BREAKPOINT%%.left",
        ],
        [
            'location' => 'outside-top',
            'cssProperty' => "margin-top",
            'affectedPropertyPath' => "design.spacing.margin.%%BREAKPOINT%%.top",
        ],
        [
            'location' => 'outside-right',
            'cssProperty' => "margin-right",
            'affectedPropertyPath' => "design.spacing.margin.%%BREAKPOINT%%.right",
        ],
        [
            'location' => 'outside-bottom',
            'cssProperty' => "margin-bottom",
            'affectedPropertyPath' => "design.spacing.margin.%%BREAKPOINT%%.bottom",
        ],
        [
            'location' => 'outside-left',
            'cssProperty' => "margin-left",
            'affectedPropertyPath' => "design.spacing.margin.%%BREAKPOINT%%.left",
        ],
    ];
}

/**
 * @return array{location:string,cssProperty:string,affectedPropertyPath:string}[]
 */
function getMarginYSpacingBars()
{
    return [
        [
            'location' => 'outside-bottom',
            'cssProperty' => "margin-bottom",
            'affectedPropertyPath' => "design.spacing.margin_bottom.%%BREAKPOINT%%",
        ],
        [
            'location' => 'outside-top',
            'cssProperty' => "margin-top",
            'affectedPropertyPath' => "design.spacing.margin_top.%%BREAKPOINT%%",
        ],
    ];
}

/**
 *
 */
