/*
 * Space Model Mixin
 *
 * Author: Harwin Borger
 *
 * @uses: (array)$layout-presets
 * @uses: (array)$layout-presets-support
 *
 * TODO building fallback for single and multiple viewport sizes. Currently you need to give up all different breakpoints in order to have it work. So you only 'small' is not enough, you still need to fill in 'medium' and 'large'
 */

$space-side-register: (
	top, right, bottom, left
);

$space-position-register: (
	absolute,
	fixed,
	relative,
) !default;

@function allow-negative-classes($settings,$type) {
	@if (map_get($settings,negative) != true) {
		@return false;
	}

	@if ($type == padding) {
		@return false;
	}

	@return true;
}

@function allow-combined-sides($type) {
	@return space-prefix-type($type);
}

@function extend-class-name($classNameArray, $extendClass) {
	$newClassName: '';

	@each $className in $classNameArray {
		@if $newClassName == '' {
			$newClassName: '#{$className}-#{$extendClass}';
		} @else {
			$newClassName: '#{$newClassName}, #{$className}-#{$extendClass}';
		}
	}

	@return $newClassName;
}

/*
* space-set-property
*
* @para $side: defines which side has to be generated
* @para $value: defines which values need to be used
* @para $type: defines what kind of type needs to be used
* @para $sign: defines whether or not a positive (1) or negative (-1) value needs to be generated.
*/

@mixin space-set-property($side, $values, $type, $sign:1) {
	$typeName: '';

	@if (space-prefix-type($type)) {
		$typeName: $type+'-';
	}

	//Set css rule like: padding-left: 5px; or margin-left: 5px;
	$cssPropertyName: false;
	$cssPropertyValue: false;

	@if ($side == false) { //Combined all values
		//Set property
		$cssPropertyName: #{$type};
		$cssPropertyValue: to-string(optimize-values($values), ' ');
	} @else {
		//Set property name based on side
		$cssPropertyName: #{$typeName+$side};
		//Retrieve variable position based on side
		$variablePosition: index($space-side-register, $side);

		//Check if values is not null
		@if ($values != null) {
			$cssPropertyValue: nth($values, $variablePosition) * $sign;
		} @else {
			@debug ('Values is not allowed to be: ' $values);
		}
	}

	//Set property
	#{$cssPropertyName}: $cssPropertyValue;
}

@mixin space-loop-sides($classNameArray, $settings, $values, $type) {
	$negative: -1;
	//Set css class like: .space-[type], .space-[type]-[size]
	#{$classNameArray} {
		@if (allow-combined-sides($type)==true) {
			@include space-set-property(false, $values, $type);
		} @else {
			@each $side in $space-side-register {
				@include space-set-property($side, $values, $type);
			}
		}
	}

	@if (allow-negative-classes($settings,$type) == true) {
		$classNameNegative: extend-class-name($classNameArray, 'negative');

		#{$classNameNegative} {
			@each $side in $space-side-register {
				@include space-set-property($side, $values, $type, $negative);
			}
		}
	}

	//Loop through different directions and add different classes
	@each $direction, $sides in map_get($settings, directions) {
		$classNameDirection: extend-class-name($classNameArray, $direction);

		//Print css class like based on sides: .space-[type]-vertical, .space-[type]-[size]-horizontal
		#{$classNameDirection} {
			@each $side in $sides {
				@include space-set-property($side, $values, $type);
			}
		}

		//Check if negative values are allowed
		@if (allow-negative-classes($settings,$type) == true) {
			//If allowed generate negative classes: .space-[type]-[direction]-negative
			$classNameDirectionNegative: extend-class-name($classNameArray, '#{$direction}-negative');

			#{$classNameDirectionNegative} {
				@each $side in $sides {
					@include space-set-property($side, $values, $type, $negative);
				}
			}
		}
	}
}

@mixin space-loop-breakpoints($className, $settings, $type) {
	@if (map_get($settings,viewports) != null) {
		$classNameArray: ('.#{$className}');

		@each $breakpoint, $values in map_get($settings, viewports) {
			// Convert value to 4 sides
			$values: convert-sides($values);
			// Convert space-unit values to rem units
			$values: convert-space-units-array($values, $breakpoint);

			//Generate breakpoints
			@include breakpoint($breakpoint) {
				@if (map_get($settings,responsive) == true and $breakpoint != 'small') {
					$breakpointClassName: '.#{$breakpoint}-#{$className}';
					$classNameArray: append($classNameArray, $breakpointClassName, comma);
				}

				@include space-loop-sides($classNameArray, $settings, $values, $type);
			}

			//Generate breakpoint only classes
			@if (map_get($settings,responsive) == true) {
				$breakpointClassName: '.#{$breakpoint}-only-#{$className}';

				@include breakpoint($breakpoint only) {
					@include space-loop-sides($breakpointClassName, $settings, $values, $type);
				}
			}
		}
	} @else {
		@warn ("Classes for '#{$className}' are not generated because 'viewports' in $space-object-settings is missing");
	}
}

@mixin space-loop-types($className, $settings) {
	@each $type, $options in map_get($settings, types) {
		$newClassName: '#{$className}-#{$type}';

		@include space-loop-breakpoints($newClassName, $settings, $type);
	}
}

@mixin space-loop-objects() {
	//Set default settings
	$defaultTypes: (
		types: map_get($layout-presets-support, types)
	);

	$defaultDirections: (
		directions: map_get($layout-presets-support, directions)
	);

	$defaultNegative: (
		negative: map_get($layout-presets-support, negative)
	);

	$defaultResponsive: (
		responsive: map_get($layout-presets-support, responsive)
	);

	@each $sizeClassName, $settings in $layout-presets {
		$className: $sizeClassName; // Generates .object

		@if (map_get($settings, types) == null) {
			$settings: map-merge($settings, $defaultTypes) // Use default settings
		}

		@if (map_get($settings, directions) == null) {
			$settings: map-merge($settings, $defaultDirections) // Use default settings
		}

		@if (map_get($settings, negative) == null) {
			$settings: map-merge($settings, $defaultNegative) // Use default settings
		}

		@if (map_get($settings, responsive) == null) {
			$settings: map-merge($settings, $defaultResponsive) // Use default settings
		}

		@include space-loop-types($className, $settings);
	}
}

/*
 * @return Layout Classes
 */
@mixin layout-classes() {
	@include space-loop-objects();
}

/************************************************
 * DEPRECATED FUNCTIONS
 */

/*
 * @return classes for using general styling
 *
 * Deprecated as of 0.2.5
 */
@mixin space-init() {
	@warn ('[DEPRECATED] - "space-init()" is deprecated since SpaceFramework [0.2.5]. Please use "layout-classes()" instead');

	@include layout-classes();
}

/*
 * @return classes for using general styling
 *
 * Deprecated as of 0.5
 */
@mixin space-model-classes() {
	@warn ('[DEPRECATED] - "space-model-classes()" is deprecated since SpaceFramework [0.5]. Please use "layout-classes()" instead');

	@include layout-classes();
}

/*
 * @return classes for using general styling
 *
 * Deprecated as of 0.18
 */
@mixin space-classes() {
	@warn ('[DEPRECATED] - "space-classes()" is deprecated since SpaceFramework [0.18]. Please use "layout-classes()" instead');

	@include layout-classes();
}
