import “../arrays/map”; import “../arrays/range”; import “scale”;

d3.scale.ordinal = function() {

return d3_scale_ordinal([], {t: "range", a: [[]]});

};

function d3_scale_ordinal(domain, ranger) {

var index,
    range,
    rangeBand;

function scale(x) {
  return range[((index.get(x) || index.set(x, domain.push(x))) - 1) % range.length];
}

function steps(start, step) {
  return d3.range(domain.length).map(function(i) { return start + step * i; });
}

scale.domain = function(x) {
  if (!arguments.length) return domain;
  domain = [];
  index = new d3_Map;
  var i = -1, n = x.length, xi;
  while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
  return scale[ranger.t].apply(scale, ranger.a);
};

scale.range = function(x) {
  if (!arguments.length) return range;
  range = x;
  rangeBand = 0;
  ranger = {t: "range", a: arguments};
  return scale;
};

scale.rangePoints = function(x, padding) {
  if (arguments.length < 2) padding = 0;
  var start = x[0],
      stop = x[1],
      step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
  range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
  rangeBand = 0;
  ranger = {t: "rangePoints", a: arguments};
  return scale;
};

scale.rangeBands = function(x, padding, outerPadding) {
  if (arguments.length < 2) padding = 0;
  if (arguments.length < 3) outerPadding = padding;
  var reverse = x[1] < x[0],
      start = x[reverse - 0],
      stop = x[1 - reverse],
      step = (stop - start) / (domain.length - padding + 2 * outerPadding);
  range = steps(start + step * outerPadding, step);
  if (reverse) range.reverse();
  rangeBand = step * (1 - padding);
  ranger = {t: "rangeBands", a: arguments};
  return scale;
};

scale.rangeRoundBands = function(x, padding, outerPadding) {
  if (arguments.length < 2) padding = 0;
  if (arguments.length < 3) outerPadding = padding;
  var reverse = x[1] < x[0],
      start = x[reverse - 0],
      stop = x[1 - reverse],
      step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)),
      error = stop - start - (domain.length - padding) * step;
  range = steps(start + Math.round(error / 2), step);
  if (reverse) range.reverse();
  rangeBand = Math.round(step * (1 - padding));
  ranger = {t: "rangeRoundBands", a: arguments};
  return scale;
};

scale.rangeBand = function() {
  return rangeBand;
};

scale.rangeExtent = function() {
  return d3_scaleExtent(ranger.a[0]);
};

scale.copy = function() {
  return d3_scale_ordinal(domain, ranger);
};

return scale.domain(domain);

}