// Wizard layouts to be generated (all by default).
// Override this variable to exclude layouts you don't need.
$aw-layouts: 'horizontal' 'vertical' !default;

// Wizard indicator styles to be generated (all by default).
// Override this variable to exclude indicator styles you don't use.
$aw-indicator-styles: 'small', 'large-filled', 'large-empty', 'large-filled-symbols', 'large-empty-symbols' !default;

// Color definitions - a mapping from indicator style and wizard step state to colors.
//
// Predefined indicator styles are: 'small', 'large-filled', 'large-empty', 'large-filled-symbols', 'large-empty-symbols'.
//
// Wizard step states are: 'default', 'current', 'done', 'optional', 'editing'.
//
// Colors are: 'border-color-default', 'background-color-default', 'symbol-color-default', 'border-color-hover',
// 'background-color-hover', 'symbol-color-hover'.  The 'hover' values are applied when the user hovers the mouse
// pointer over a navigable wizard step indicator.  Otherwise the 'default' values are used.
//
// Notes:
// - The order of wizard step states in this mapping does not affect the order of resulting CSS rules, which is fixed
//   internally by angular-archwizard (see `aw-define-style` mixin).
// - Depending on the active indicator style, some colors may not be used.  For example, 'background-color-default' and
//   'background-color-hover' do not make sense in 'large-empty-symbols' indicator style.
//
// 'Null' colors
// -------------
//
// You can use `null` instead of a color value to exclude the corresponding property from CSS output.  For example,
//
//   $aw-colors: (
//     '_': (
//       'editing': (
//         'border-color-default': null,
//         'border-color-hover': null
//       )
//     )
//   )
//
//   will turn off red border for wizard steps in 'editing' state.
//
// Default colors
// --------------
//
// You can set default colors by using '_' in place of an indicator style or a wizard step state.
// The `aw-get-color` function looks up the requested color in the following order, picking the first defined entry:
//
// - $aw-colors[$indicator-style][$step-state][$color]
// - $aw-colors[$indicator-style]['_'][$color]
// - $aw-colors['_'][$step-state][$color]
// - $aw-colors['_']['_'][$color]
//
$aw-colors: (
  '_': (
    'default': (
      'border-color-default': #E6E6E6,
      'background-color-default': #E6E6E6,
      'symbol-color-default': #E6E6E6,
      'border-color-hover': darken(#E6E6E6, 10%),
      'background-color-hover': darken(#E6E6E6, 5%),
      'symbol-color-hover': darken(#E6E6E6, 10%),
    ),
    'current': (
      'border-color-default': #808080,
      'background-color-default': #808080,
      'symbol-color-default': #808080,
      'border-color-hover': darken(#808080, 10%),
      'background-color-hover': darken(#808080, 5%),
      'symbol-color-hover': darken(#808080, 10%),
    ),
    'done': (
      'border-color-default': #339933,
      'background-color-default': #339933,
      'symbol-color-default': #339933,
      'border-color-hover': darken(#339933, 10%),
      'background-color-hover': darken(#339933, 5%),
      'symbol-color-hover': darken(#339933, 10%),
    ),
    'optional': (
      'border-color-default': #38ef38,
      'background-color-default': #38ef38,
      'symbol-color-default': #38ef38,
      'border-color-hover': darken(#38ef38, 10%),
      'background-color-hover': darken(#38ef38, 5%),
      'symbol-color-hover': darken(#38ef38, 10%),
    ),
    'editing': (
      'border-color-default': #FF0000,
      'background-color-default': #FF0000,
      'symbol-color-default': #FF0000,
      'border-color-hover': darken(#FF0000, 10%),
      'background-color-hover': darken(#FF0000, 5%),
      'symbol-color-hover': darken(#FF0000, 10%),
    ),
  ),
  'large-filled-symbols': (
    '_': (
      'symbol-color-default': black,
      'symbol-color-hover': black,
    )
  )
) !default;

// line color
$aw-line-color: #E6E6E6 !default;

// label colors
$aw-label-color-default: #808080 !default;
$aw-label-color-hover: darken($aw-label-color-default, 20%) !default;

// Circle definitions
//
// Circles are the visual representation of wizard steps in the navigation bar.  Depending on
// the step indicator style selected for the wizard, circles are either small (indicator style 'small')
// or big (indicator styles 'large-filled', 'large-empty', 'large-filled-symbols' etc.).
//
// A short summary of available configuration options:
// - dot-border-width defines circle border width
// - dot-width defines the horizontal dimension of circles
// - dot-height defines the vertical dimension of circles
//
// It is recommended to always have dot-width equal to dot-height.
//
$aw-circle-border-width: 2px !default;

// small definitions
$aw-small-circle-width: 14px !default;
$aw-small-circle-height: 14px !default;

// big definitions
$aw-big-circle-width: 50px !default;
$aw-big-circle-height: 50px !default;

// padding between text and baseline, for horizonal navigation bar
$aw-text-padding-bottom: 10px !default;

// padding between text and baseline, for vertical navigation bar
$aw-text-margin-left: 15px !default;

// distance between steps, for vertical navigation bar
$aw-distance-between-steps: 10px !default;

$aw-text-height: 14px !default;

// declare global variables
$aw-param-indicator-width: null;
$aw-param-indicator-height: null;
$aw-param-indicator-border-width: null;


// Temporary variables used to pass parameters from the `define-style` mixin to its content block.
// They will no longer be needed after content arguments support is released:
//
// - https://github.com/sass/sass/issues/871
// - https://github.com/sass/libsass/releases
// - https://github.com/sass/node-sass/releases/
//
// Using global variables is the recommended workaround
//
// - https://github.com/sass/sass/issues/626#issuecomment-345432420
// - https://github.com/sass/sass/issues/871
//
// indicator state: 'default' or 'hover'
$aw-param-indicator-state: null;

// wizard step state: 'default', 'current', 'done' etc.
$aw-param-step-state: null;

@mixin rtl {
  @at-root [dir="rtl"] #{&} {
    @content;
  }
}

// Defines the line that strings together circles representing wizard steps, in the horizontal layout
@mixin aw-horizontal-line($dot-width, $dot-height, $line-color) {
  background-color: $line-color;
  content: '';
  position: absolute;
  height: 1px;
  width: calc(100% - #{$dot-width});
  top: -($dot-height / 2);
  left: calc(50% + #{$dot-width / 2});

  @include rtl {
    left: auto;
    right: calc(50% + #{$dot-width / 2});
  }
}

// Defines the line that strings together circles representing wizard steps, in the vertical layout
@mixin aw-vertical-line($dot-width, $dot-height, $line-color) {
  background-color: $line-color;
  content: '';
  position: absolute;
  left: -($dot-height / 2);
  top: $dot-height;
  height: calc(100% - #{$dot-height});
  width: 1px;

  @include rtl {
    left: auto;
    right: -($dot-height / 2);
  }
}

// Defines a circle representing a wizard step
@mixin aw-circle($dot-width, $dot-height, $dot-border-width) {
  position: absolute;
  width: $dot-width;
  height: $dot-height;
  text-align: center;
  vertical-align: middle;
  line-height: $dot-height - 2 * $dot-border-width;
  transition: 0.25s;
  border-radius: 100%;
}

// Positions a circle in the horizontal layout of the navigation bar
@mixin aw-circle-position-horizontal($dot-width, $dot-height, $dot-border-width) {
  top: -$dot-height;
  left: calc(50% - #{$dot-width / 2});

  @include rtl {
    left: auto;
    right: calc(50% - #{$dot-width / 2});;
  }
}

// Positions a circle in the vertical layout of the navigation bar
@mixin aw-circle-position-vertical($dot-width, $dot-height, $dot-border-width) {
  top: 0;
  left: -$dot-width;

  @include rtl {
    left: auto;
    right: -$dot-width;
  }
}

// Define a step indicator style like 'small', 'large-filled' etc.
//
// Arguments:
//   $layout - 'horizontal' | 'vertical'
//   $width  - step indicator width
//   $height - step indicator height
//   $border-width - step indicator border width
//
// Apart from the arguments, the `define-style` mixin receives a content block,
// which is applied for .step-indicator elements and is expected to customize indicator representation.
// The content block is invoked several times, each time with different arguments passed through global variables:
//
//   - $aw-param-indicator-state - indicator state: 'default' or 'hover'
//   - $aw-param-step-state - wizard step state: 'default', 'current', 'done' etc.
//
// In addition to these variables, the content block can use the following
// variables passed through the `define-style` mixin:
//
//   - $aw-param-indicator-width - equals to $width argument of the `define-style` mixin
//   - $aw-param-indicator-height - equals to $height argument of the `define-style` mixin
//   - $aw-param-indicator-border-width - equals to $border-width argument of the `define-style` mixin
//
@mixin aw-define-style($layout, $width: $aw-big-circle-height, $height: $aw-big-circle-height, $border-width: $aw-circle-border-width) {

  // Make variables accessible from the content block
  $aw-param-indicator-width: $width !global;
  $aw-param-indicator-height: $height !global;
  $aw-param-indicator-border-width: $border-width !global;

  @if ($layout == 'horizontal') {
    padding: ($height + $aw-text-padding-bottom) 0 $aw-text-padding-bottom 0;
  }
  @else if ($layout == 'vertical') {
    padding: ($aw-distance-between-steps / 2) ($aw-distance-between-steps / 2) ($aw-distance-between-steps / 2) ($aw-distance-between-steps / 2 + $height);

    @include rtl {
      padding: ($aw-distance-between-steps / 2) ($aw-distance-between-steps / 2 + $height) ($aw-distance-between-steps / 2) ($aw-distance-between-steps / 2);
    }
  }

  li {
    &:not(:last-child):after {
      @if ($layout == 'horizontal') {
        @include aw-horizontal-line($width, $height, $aw-line-color);
      }
      @else if ($layout == 'vertical') {
        @include aw-vertical-line($width, $height, $aw-line-color);
      }
    }

    @if ($layout == 'vertical') {
      a {
        min-height: $height;
      }
    }

    .step-indicator {
      @if ($layout == 'horizontal') {
        @include aw-circle-position-horizontal($width, $height, $border-width);
      }
      @else if ($layout == 'vertical') {
        @include aw-circle-position-vertical($width, $height, $border-width);
      }

      $aw-param-indicator-state: 'default' !global;
      $aw-param-step-state: 'default' !global;
      @include aw-circle($width, $height, $border-width);
      @content;
    }
    &.optional .step-indicator {
      $aw-param-indicator-state: 'default' !global;
      $aw-param-step-state: 'optional' !global;
      @content;
    }
    &.done .step-indicator {
      $aw-param-indicator-state: 'default' !global;
      $aw-param-step-state: 'done' !global;
      @content;
    }
    &.current .step-indicator {
      $aw-param-indicator-state: 'default' !global;
      $aw-param-step-state: 'current' !global;
      @content;
    }
    &.editing .step-indicator {
      $aw-param-indicator-state: 'default' !global;
      $aw-param-step-state: 'editing' !global;
      @content;
    }
    // 'completed' class takes priority
    // https://github.com/madoar/angular-archwizard/pull/221
    &.completed .step-indicator {
      $aw-param-indicator-state: 'default' !global;
      $aw-param-step-state: 'done' !global;
      @content;
    }

    &.navigable a:hover .step-indicator {
      $aw-param-indicator-state: 'hover' !global;
      $aw-param-step-state: 'default' !global;
      @include aw-circle($width, $height, $border-width);
      @content;
    }
    &.navigable.optional a:hover .step-indicator {
      $aw-param-indicator-state: 'hover' !global;
      $aw-param-step-state: 'optional' !global;
      @content;
    }
    &.navigable.done a:hover .step-indicator {
      $aw-param-indicator-state: 'hover' !global;
      $aw-param-step-state: 'done' !global;
      @content;
    }
    &.navigable.current a:hover .step-indicator {
      $aw-param-indicator-state: 'hover' !global;
      $aw-param-step-state: 'current' !global;
      @content;
    }
    &.navigable.editing a:hover .step-indicator {
      $aw-param-indicator-state: 'hover' !global;
      $aw-param-step-state: 'editing' !global;
      @content;
    }
    // 'completed' class takes priority
    // https://github.com/madoar/angular-archwizard/pull/221
    &.navigable.completed a:hover .step-indicator {
      $aw-param-indicator-state: 'hover' !global;
      $aw-param-step-state: 'done' !global;
      @content;
    }
  }
}


// Define wizard styles specific to the configurated layouts (`$aw-layouts`) and indicator styles (`$aw-indicator-styles`)
@mixin aw-define-styles() {

  // For each layout and indicator style...
  @each $layout in $aw-layouts {
    aw-wizard-navigation-bar.#{$layout} {
      @each $indicator-style in $aw-indicator-styles {
        &.#{$indicator-style} ul.steps-indicator {
          // ...we are emitting CSS styles for `aw-wizard-navigation-bar.<layout>.<indicator-style> ul.steps-indicator`

          // Each indicator style is defined with its specific values (like `$border-width: 0` in this case) and CSS
          // properties.  For indicator style 'small' we only define background color, while for other indicator styles
          // below we define border and/or color properties.  The `aw-define-style` mixin here is used to apply CSS
          // properties in a proper order for each wizard step state ('default', 'current', 'done' etc.)
          @if $indicator-style == 'small' {
            @include aw-define-style($layout, $width: $aw-small-circle-width, $height: $aw-small-circle-height, $border-width: 0) {
              background-color: aw-get-color($indicator-style, $aw-param-step-state, $aw-param-indicator-state, 'background-color');
            }
          }

          @else if $indicator-style == 'large-filled' {
            @include aw-define-style($layout, $border-width: 0) {
              background-color: aw-get-color($indicator-style, $aw-param-step-state, $aw-param-indicator-state, 'background-color');
            }
          }

          @else if $indicator-style == 'large-empty' {
            @include aw-define-style($layout) {
              $border-color: aw-get-color($indicator-style, $aw-param-step-state, $aw-param-indicator-state, 'border-color');
              @if $border-color != null {
                // To optimize CSS output size, do not define any border styles when border-color is null
                border: $aw-param-indicator-border-width solid $border-color;
              }
            }
          }

          @else if $indicator-style == 'large-filled-symbols' {
            @include aw-define-style($layout, $border-width: 0) {
              background-color: aw-get-color($indicator-style, $aw-param-step-state, $aw-param-indicator-state, 'background-color');
              color: aw-get-color($indicator-style, $aw-param-step-state, $aw-param-indicator-state, 'symbol-color');
            }
          }

          @else if $indicator-style == 'large-empty-symbols' {
            @include aw-define-style($layout) {
              $border-color: aw-get-color($indicator-style, $aw-param-step-state, $aw-param-indicator-state, 'border-color');
              @if $border-color != null {
                // To optimize CSS output size, do not define any border styles when border-color is null
                border: $aw-param-indicator-border-width solid $border-color;
              }
              color: aw-get-color($indicator-style, $aw-param-step-state, $aw-param-indicator-state, 'symbol-color');
            }
          }
        }
      }
    }
  }
}

// Retrieve color from the color definitions map ($aw-colors)
//
// Arguments:
//   $indicator-style: Indicator style: 'small', 'large-filled' etc.
//   $step-state:      Wizard step state: 'default', 'current', 'done' etc.
//   $indicator-state: Indicator state: 'default' or 'hover'
//   $property:        Property to retrieve: 'background-color', 'border-color', 'symbol-color'
//
// Returns:
//   Color value like #E6E6E6 or `null` if
//     - the requested property is not specified in the color definitions map
//     - the corresponding color definitions map entry is explicit `null`
//
@function aw-get-color($indicator-style, $step-state, $indicator-state, $property) {
  //
  // Gather a list of candidate maps to search for the requested property.
  // As documented in archwizard.scss, "Default Colors" section, the order should be as follows:
  //
  // - $aw-colors[$indicator-style][$step-state][$color]
  // - $aw-colors[$indicator-style]['_'][$color]
  // - $aw-colors['_'][$step-state][$color]
  // - $aw-colors['_']['_'][$color]
  //
  // Additional "or ()" expressions are necessary because calling `map-get(null)` causes an SCSS compilation error
  //
  $maps: (
    map-get(map-get($aw-colors, $indicator-style) or (), $step-state) or (),
    map-get(map-get($aw-colors, $indicator-style) or (), '_') or (),
    map-get(map-get($aw-colors, '_') or (), $step-state) or (),
    map-get(map-get($aw-colors, '_') or (), '_') or (),
  );

  // Loop through $maps until we find the requested property
  $key: '#{$property}-#{$indicator-state}';
  @each $map in $maps {
    @if map-has-key($map, $key) {
      @return map-get($map, $key);
    }
  }
  @return null;
}
