// Devuelve true si el breakpoint es parte del core
@function isCoreBreakpoint($bp){
  @if map-get($breakpoints,$bp) {
    @return true
  } @else {
    @return false
  }
}

// Devuelve true si el breakpint es válido (em, rem, px)
@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
  }
}

// Obtiene un breakpoint del core
@function getBp($bp){
  @return map-get($breakpoints,$bp)
}

// Convierte un valor en em o rem a px
@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"
  }
}

// From (mayor que $bp)
@mixin from($from){
  @if isCoreBreakpoint($from){
    @if $from == s {
      @content
    }
    @else {
      @media screen and (min-width: getBp($from)){ @content }
    }
  } @else if isValidBreakpoint($from){
    @media screen and (min-width: $from){ @content }
  } @else {
    @error 'El mixin from() solo puede recibir un breakpoint del Core (#{map-keys($breakpoints)}) o un número en px, em o rem'
  }
}

// To (es menor que $to)
@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($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($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($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($breakpoints)}) o números en px, em o rem';
  }
}
