// @import '~sass-unitconverter/unitconverter';
// @import 'utils';
// @import 'break-points';

// ** Options ******************************************************************
// == Global Options ===========================================================
$fls-mode:   fluid !default; // fluid or fit, vw-only
$fls-device:   min !default; // min   or max, devices's key(Ex. phone, tablet, ...)
$fls-unit:    each !default; // each  or units(Ex. px, em, rem, ...)
$fls-breakunit: px !default; // units(Ex. px, em, rem, ...)
$fls-min:     null !default; // null  or length(Ex. 20px, 20pt, ...)
$fls-max:     null !default; // null  or length(Ex. 20px, 20pt, ...)
$fls-limit:   size !default; // size  or break
$fls-class:  false !default; // false or true
$fls-safari-iframe-fix: false !default; // false or true

// == Mapping ==================================================================
// -- Mapping with API Name --
@function global-options() {
  $global-options: (
//  Global Name. Global Variable.
    mode:        $fls-mode,
    device:      $fls-device,
    unit:        $fls-unit,
    breakunit:   $fls-breakunit,
    min:         $fls-min,
    max:         $fls-max,
    limit:       $fls-limit,
    class:       $fls-class,
    iframe-fix:  $fls-safari-iframe-fix,

    // Unit Converter
    root-size:   $root-font-size,
    base-size:   $base-font-size,
  );
  @return $global-options;
}

// -- Mapping with Scoped Options --
$fluid-options-map: (
// Scoped Name. Global Name.
   mode:        mode,
   device:      device,
   unit:        unit,
   breakunit:   breakunit,
   min:         min,
   min-size:    min,
   max:         max,
   max-size:    max,
   limit:       limit,
   class:       class,
   iframe:      iframe-fix,
   iframe-fix:  iframe-fix,
   safari-iframe-fix: iframe-fix,

   // Unit Converter
   root:        root-size,
   root-size:   root-size,
   size-root:   root-size,
   base:        base-size,
   base-size:   base-size,
   size-base:   base-size,
);

// -- Mapping with Types --
$unit-types: map-keys(n-units(0)) !default;
$bool-types: true false;
@function fluid-types() {
  $fluid-types: (
//  Global Name. Types.
    mode:        fluid fit vw-only,
    device:      join(min max, map-keys($breakpoints)),
    unit:        join(each, $unit-types),
    breakunit:   $unit-types,
    min:         join(null, $unit-types),
    max:         join(null, $unit-types),
    limit:       size break,
    class:       $bool-types,
    iframe-fix:  $bool-types,

    // Unit Converter
    root-size:   $unit-types,
    base-size:   $unit-types,
  );
  @return $fluid-types;
}

// == Get ======================================================================
@function scoped-convert($scoped-options) {
  // Option Empty
  @if length($scoped-options) == 0 {
    @return ();
  }

  // Replace key to Global Name
  $result: ();
  @each $key, $value in $scoped-options {
    $global-key: map-get($fluid-options-map, $key);
    $result:     map-merge($result, ($global-key: $value));
  }
  @return $result;
}

@function name-convert($name) {
  $result: ();
  @if is-list($name) {
    @each $key in $name {
      $global-key: map-get($fluid-options-map, $key);
      $result: append($result, $global-key);
    }
  }
  @else {
    $result: map-get($fluid-options-map, $name);
  }
  @return $result;
}

@function get-option-value($scoped, $name) {
  @return if(map-has-key($scoped, $name),
             map-get($scoped, $name),
             map-get(global-options(), $name));
}

// -- Interface --
@function get-option($options: (), $name: all) {
  $scoped: scoped-convert($options);
  $result: ();

  @if $name == all {
    $result: map-merge(global-options(), $scoped);
  }
  @else {
    $name: name-convert($name);

    @if is-list($name) {
      @each $option in $name {
        $value:  get-option-value($scoped, $option);
        $result: append($result, $value);
      }
    }
    @else {
      $result: get-option-value($scoped, $name);
    }
  }
  @return $result;
}

// == Validation ===============================================================
$CACHED-GLOBAL-OPTIONS: global-options()   !default;
$CACHED-FLUID-OPTIONS:  $fluid-options-map !default;
$CACHED-OPTIONS-KEYS:   ()                 !default;
$CACHED-ALL-OPTIONS:    global-options()   !default;
$CACHED-FLUID-TYPES:    fluid-types()      !default;

@function check-option($criteria-name, $target-name, $target-type, $option-criteria, $options) {
  @each $option in $options {
    @if not contain($option-criteria, $option) {
      @error "#{$target-name}'s #{$target-type}, #{$option} doesn't exist at #{$criteria-name}";
      @return false;
    }
  }
  @return true;
}

// -- Interface --
@function validate-options($options: ()) {
  $validate-mapping: false;
  $validate-keys:    false;
  $validate-types:   true;

  // - Check api name -
  // Mapping check
  $global-options:       global-options();
  $mapping-names: map-values($fluid-options-map);
  @if not ($CACHED-GLOBAL-OPTIONS == $global-options and
           $CACHED-FLUID-OPTIONS  == $fluid-options-map) {
    $validate-mapping: check-option("global-options", "$fluid-options-map", "global name",
                                    $global-options, $mapping-names);

    $CACHED-GLOBAL-OPTIONS: $global-options    !global;
    $CACHED-FLUID-OPTIONS:  $fluid-options-map !global;
  }

  // Exist key check
  $options-keys: map-keys($options);
  @if not contain($CACHED-OPTIONS-KEYS, $options-keys) {
    $validate-keys: check-option("$fluid-options-map key", "$options", "key",
                                 $fluid-options-map, $options-keys);

    $CACHED-OPTIONS-KEYS: map-merge($CACHED-OPTIONS-KEYS, ($options-keys: true)) !global;
  }

  // - Check each type -
  $all-options: get-option($options);
  $all-options-keys: map-keys($all-options);

  $fluid-types: fluid-types();
  @if not ($CACHED-ALL-OPTIONS == $all-options and $CACHED-FLUID-TYPES == $fluid-types) {
    @each $all-options-key in $all-options-keys {
      $fluid-type:   map-get($fluid-types, $all-options-key);
      $option-value: map-get($all-options, $all-options-key);

      // Case min or max
      @if contain('min' 'max', $all-options-key) {
        $option-value: if(is-null($option-value), $option-value, get-unit($option-value));
      }

      // Case root-size or base-size
      @if contain('root-size' 'base-size', $all-options-key) {
        $option-value: get-unit($option-value);
      }

      // Case not contain in types
      @if not contain($fluid-type, $option-value) {
        @error "$options's value #{$option-value} doesn't exist at fluid-types";
        $validate-types: false;
      }
    }

    $CACHED-ALL-OPTIONS: $all-options !global;
    $CACHED-FLUID-TYPES: $fluid-types !global;
  }

  @return $validate-mapping and $validate-keys and $validate-types;
}
