////
/// Copyright (c) 2016-2020 Martin Donath <martin.donath@squidfunk.com>
///
/// Permission is hereby granted, free of charge, to any person obtaining a
/// copy of this software and associated documentation files (the "Software"),
/// to deal in the Software without restriction, including without limitation
/// the rights to use, copy, modify, merge, publish, distribute, sublicense,
/// and/or sell copies of the Software, and to permit persons to whom the
/// Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in
/// all copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
/// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
/// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
/// DEALINGS
////

// ----------------------------------------------------------------------------
// Variables
// ----------------------------------------------------------------------------

///
/// Device-specific breakpoints
///
/// @example
///   $break-devices: (
///     mobile: (
///       portrait:  220px  479px,
///       landscape: 480px  719px
///     ),
///     tablet: (
///       portrait:  720px  959px,
///       landscape: 960px  1219px
///     ),
///     screen: (
///       small:     1220px 1599px,
///       medium:    1600px 1999px,
///       large:     2000px
///     )
///   );
///
@use "sass:map";
@use "sass:list";
@use "sass:meta";
@use "./convert";

$break-devices: (
  mobile: (
    portrait:  convert.px2em(220px)  convert.px2em(479px),
    landscape: convert.px2em(480px)  convert.px2em(719px)
  ),
  tablet: (
    portrait:  convert.px2em(720px)  convert.px2em(959px),
    landscape: convert.px2em(960px)  convert.px2em(1219px)
  ),
  screen: (
    small:     convert.px2em(1220px) convert.px2em(1599px),
    medium:    convert.px2em(1600px) convert.px2em(1999px),
    large:     convert.px2em(2000px)
  )
) !default;

// ----------------------------------------------------------------------------
// Helpers
// ----------------------------------------------------------------------------

///
/// Choose minimum and maximum device widths
///
@function break-select-min-max($devices) {
  $min: 1000000;
  $max: 0;
  @each $key, $value in $devices {
    @while meta.type-of($value) == map {
      $value: break-select-min-max($value);
    }
    @if meta.type-of($value) == list {
      @each $number in $value {
        @if meta.type-of($number) == number {
          $min: min($number, $min);
          @if $max != null {
            $max: max($number, $max);
          }
        } @else {
          @error "Invalid number: #{$number}";
        }
      }
    } @else if meta.type-of($value) == number {
      $min: min($value, $min);
      $max: null;
    } @else {
      @error "Invalid value: #{$value}";
    }
  }
  @return $min, $max;
}

///
/// Select minimum and maximum widths for a device breakpoint
///
@function break-select-device($device) {
  $current: $break-devices;
  @for $n from 1 through list.length($device) {
    @if meta.type-of($current) == map {
      $current: map.get($current, list.nth($device, $n));
    } @else {
      @error "Invalid device map: #{$devices}";
    }
  }
  @if meta.type-of($current) == list or meta.type-of($current) == number {
    $current: (default: $current);
  }
  @return break-select-min-max($current);
}

// ----------------------------------------------------------------------------
// Mixins
// ----------------------------------------------------------------------------

///
/// A minimum-maximum media query breakpoint
///
@mixin break-at($breakpoint) {
  @if meta.type-of($breakpoint) == number {
    @media screen and (min-width: $breakpoint) {
      @content;
    }
  } @else if meta.type-of($breakpoint) == list {
    $min: list.nth($breakpoint, 1);
    $max: list.nth($breakpoint, 2);
    @if meta.type-of($min) == number and meta.type-of($max) == number {
      @media screen and (min-width: $min) and (max-width: $max) {
        @content;
      }
    } @else {
      @error "Invalid breakpoint: #{$breakpoint}";
    }
  } @else {
    @error "Invalid breakpoint: #{$breakpoint}";
  }
}

///
/// An orientation media query breakpoint
///
@mixin break-at-orientation($breakpoint) {
  @if meta.type-of($breakpoint) == string {
    @media screen and (orientation: $breakpoint) {
      @content;
    }
  } @else {
    @error "Invalid breakpoint: #{$breakpoint}";
  }
}

///
/// A maximum-aspect-ratio media query breakpoint
///
@mixin break-at-ratio($breakpoint) {
  @if meta.type-of($breakpoint) == number {
    @media screen and (max-aspect-ratio: $breakpoint) {
      @content;
    }
  } @else {
    @error "Invalid breakpoint: #{$breakpoint}";
  }
}

///
/// A minimum-maximum media query device breakpoint
///
@mixin break-at-device($device) {
  @if meta.type-of($device) == string {
    $device: $device,;
  }
  @if meta.type-of($device) == list {
    $breakpoint: break-select-device($device);
    @if list.nth($breakpoint, 2) != null {
      $min: list.nth($breakpoint, 1);
      $max: list.nth($breakpoint, 2);
      @media screen and (min-width: $min) and (max-width: $max) {
        @content;
      }
    } @else {
      @error "Invalid device: #{$device}";
    }
  } @else {
    @error "Invalid device: #{$device}";
  }
}

///
/// A minimum media query device breakpoint
///
@mixin break-from-device($device) {
  @if meta.type-of($device) == string {
    $device: $device,;
  }
  @if meta.type-of($device) == list {
    $breakpoint: break-select-device($device);
    $min: list.nth($breakpoint, 1);
    @media screen and (min-width: $min) {
      @content;
    }
  } @else {
    @error "Invalid device: #{$device}";
  }
}

///
/// A maximum media query device breakpoint
///
@mixin break-to-device($device) {
  @if meta.type-of($device) == string {
    $device: $device,;
  }
  @if meta.type-of($device) == list {
    $breakpoint: break-select-device($device);
    $max: list.nth($breakpoint, 2);
    @media screen and (max-width: $max) {
      @content;
    }
  } @else {
    @error "Invalid device: #{$device}";
  }
}
