@use '../variables.scss' as var;

@function isCoreBreakpoint($bp) {
  @if map-get(var.$breakpoints, $bp) {
    @return true
  }

  @else {
    @return false
  }
}

@function isValidBreakpoint($bp) {
  @if type-of($bp)==number and (unit($bp)=='px' or unit($bp)=='em' or unit($bp)=='rem') {
    @return true
  }

  @else {
    @return false
  }
}

@function getBp($bp) {
  @return map-get(var.$breakpoints, $bp)
}

@function toPx($value) {
  @if type-of($value)==number {
    @if unit($value)=='em' {
      @return ($value / 1em) * 16px;
    }

    @else if unit($value)=='rem' {
      @return ($value / 1rem) * 16px
    }

    @else if unit($value)=='px' {
      @return $value;
    }

    @else {
      @error "La funcion toPx() solo acepta numeros en em o rem o px"
    }
  }

  @else {
    @error "La funcion toPx() solo acepta numeros en em o rem"
  }
}

@mixin from($from) {

  @if isCoreBreakpoint($from) {

    // no imprime media query para tamaño s
    @if $from ==s {
      @content
    }

    // imprime media query en los otros tamaños
    @else {
      @media screen and (min-width: getBp($from)) {
        @content
      }
    }
  }

  @else if isValidBreakpoint($from) {
    @media screen and (min-width: $from) {
      @content
    }
  }

  // Error
  @else {
    @error 'El mixin from() solo puede recibir un breakpoint del Core (#{map-keys(var.$breakpoints)}) o un número en px, em o rem'
  }
}


@mixin to($to) {

  // Si es un breakpoint del core
  @if isCoreBreakpoint($to) {
    @if $to ==s {
      @content;
    }

    @else {
      @media screen and (max-width : getBp($to) - 1px) {
        @content
      }
    }
  }

  // Si es un breakpoint válido (px, em, rem)
  @else if isValidBreakpoint($to) {
    @media screen and (max-width: toPx($to) - 1px) {
      @content
    }
  }

  // Si no es un breakpoint válido lanzar error
  @else {
    @error 'El mixin to() solo puede recibir un breakpoint del Core (#{map-keys(var.$breakpoints)}) o un número en px, em o rem'
  }
}

@mixin fromTo($from, $to) {

  // Si ambos son breakpoints del core
  @if isCoreBreakpoint($from) and isCoreBreakpoint($to) {
    @if getBp($to)>getBp($from) {
      @media screen and (min-width : getBp($from)) and (max-width : getBp($to) - 1px) {
        @content
      }
    }

    @else {
      @error "El segundo argumento del mixin fromTo debe ser mayor que el primero"
    }
  }

  // Si solo $from es breakpoint del core
  @else if isCoreBreakpoint($from) and not isCoreBreakpoint($to) {
    @if isValidBreakpoint($to) {
      @if toPx($to)>toPx(getBp($from)) {
        @media screen and (min-width : getBp($from)) and (max-width : toPx($to) - 1px) {
          @content
        }
      }

      @else {
        @error "El segundo argumento del mixin fromTo debe ser mayor que el primero"
      }
    }

    @else {
      @error "El segundo argumento del mixin fromTo() debe ser un breakpoint del Core (#{map-keys(var.$breakpoints)}) o un número en px, em o rem"
    }
  }

  // Si solo $to es breakpoint del core
  @else if not isCoreBreakpoint($from) and isCoreBreakpoint($to) {
    @if isValidBreakpoint($from) {
      @if toPx(getBp($to))>toPx($from) {
        @media screen and (min-width : $from) and (max-width : getBp($to) - 1px) {
          @content
        }
      }

      @else {
        @error "El segundo argumento del mixin fromTo debe ser mayor que el primero"
      }
    }

    @else {
      @error "El primer argumento del mixin fromTo() debe ser un breakpoint del Core (#{map-keys(var.$breakpoints)}) o un número en px, em o rem"
    }
  }

  // Si no son breakpoints del core pero son breakpoints válidos (px, em, rem)
  @else if isValidBreakpoint($from) and isValidBreakpoint($to) {
    @if toPx($to)>toPx($from) {
      @media screen and (min-width : $from) and (max-width : toPx($to) - 1px) {
        @content
      }
    }

    @else {
      @error "El segundo argumento del mixin fromTo debe ser mayor que el primero"
    }
  }

  // Si al menos hay un breakpoint inválido
  @else {
    @error 'Los argumentos del mixin fromTo() deben ser breakpoints del Core (#{map-keys(var.$breakpoints)}) o números en px, em o rem';
  }
}
