@use "spacing";
@use "breakpoints";
@use "sass:map";

// Grid gutters
$grid-gutter: (
  "xs": spacing.$spacing-4,
  "sm": spacing.$spacing-4,
  "md": spacing.$spacing-6,
  "lg": spacing.$spacing-6,
  "xl": spacing.$spacing-6,
) !default;

// Grid columns
$grid-columns: (
  "xs": 12,
  "sm": 12,
  "md": 12,
  "lg": 12,
  "xl": 12,
) !default;

// Well padding
$well-padding: (
  "xs": spacing.$spacing-4,
  "sm": spacing.$spacing-8,
  "md": spacing.$spacing-8,
  "lg": 200px,
  "xl": 200px,
) !default;

// Well content max width
$well-content-max-width: (
  "xs": 840px,
  "sm": 840px,
  "md": 840px,
  "lg": 1040px,
  "xl": 1040px,
) !default;

// Mixin to define the spacing variables used for the well bounds
// NOTE: we pull this out as a separate mixin so that applications can choose
// to define the variables at a higher level than a `Well` component if they
// need to
@mixin well-vars {
  --Well-padding: #{map.get($well-padding, "xs")};
  --Well-content-max-width: #{map.get($well-content-max-width, "xs")};
  --Well-content-width: min(
    100% - 2 * var(--Well-padding),
    var(--Well-content-max-width)
  );

  @each $breakpoint in map.keys($well-padding) {
    @include breakpoints.breakpoint-at-least($breakpoint) {
      --Well-padding: #{map.get($well-padding, $breakpoint)};
      --Well-content-max-width: #{map.get(
          $well-content-max-width,
          $breakpoint
        )};
    }
  }
}

// Mixin to define the spacing variables used for the grid layout
// NOTE: we pull this out as a separate mixin so that applications can choose
// to define the variables at a higher level than a `Grid` component if they
// need to
@mixin grid-vars {
  --Grid-gutter: #{map.get($grid-gutter, "xs")};
  --Grid-columns: #{map.get($grid-columns, "xs")};

  @each $breakpoint in map.keys($grid-gutter) {
    @include breakpoints.breakpoint-at-least($breakpoint) {
      --Grid-gutter: #{map.get($grid-gutter, $breakpoint)};
      --Grid-columns: #{map.get($grid-columns, $breakpoint)};
    }
  }
}

// Mixin to define the outer well container with a max body width and padding
// on the sides
@mixin well {
  padding: 0 var(--Well-padding);
  margin-left: auto;
  margin-right: auto;
  max-width: calc(var(--Well-content-max-width) + 2 * var(--Well-padding));

  @include well-vars();
}

// Mixin to define a basic grid with a responsive gutter and number of columns
@mixin grid {
  display: flex;
  flex-wrap: wrap;
  margin-left: calc(-0.5 * var(--Grid-gutter));
  margin-right: calc(-0.5 * var(--Grid-gutter));

  @include grid-vars();

  & > * {
    width: 100%;
    max-width: 100%;
  }
}

// Mixin to define a grid item that can specify an optional column span and
// offset. Must be used in the context of a grid container.
@mixin grid-item-columns-auto-layout() {
  flex: 1 0;
}

@mixin grid-item-columns($columns) {
  width: calc(#{$columns} / var(--Grid-columns) * 100%);
  flex: 0 0 auto;
}

@mixin grid-item-offset($offset) {
  margin-left: calc(#{$offset} / var(--Grid-columns) * 100%);
}

@mixin grid-item($columns: 0, $offset: 0, $auto-layout: true) {
  @if $auto-layout {
    @include grid-item-columns-auto();
  }

  @if $columns > 0 {
    @include grid-item-columns($columns);
  }

  @if $offset > 0 {
    @include grid-item-offset($offset);
  }

  padding: 0 calc(0.5 * var(--Grid-gutter));
}

@function get-align-with-grid($offset: 0) {
  $padding-left: calc(((100% - var(--Well-content-width)) / 2));
  $gap-total: calc(var(--Grid-gutter) * (var(--Grid-columns) - 1));
  $column-total: calc(var(--Well-content-width) - #{$gap-total});
  $column-offset: calc(
    #{$offset} * #{$column-total} / var(--Grid-columns)
  );
  $gap-offset: calc(var(--Grid-gutter) * #{$offset});

  @return calc(#{$padding-left} + #{$column-offset} + #{$gap-offset});
}

@mixin align-left-with-grid($offset: 0) {
  padding-left: get-align-with-grid($offset);
}
