#pragma once

#include <euler/syscall.hpp>
#include <stdint.h>

namespace daguerre {

  typedef euler::syscall::encoded_color hilbert_color;

  struct rgb24 {
    uint8_t r;
    uint8_t g;
    uint8_t b;
  };

  template <class dest_t, class src_t>
  using converter_t = void (dest_t &, const src_t &);

  //copies src to dest
  template <class color_t>
  static inline void default_conversion(color_t &dest, const color_t &src) {
    dest = src;
  }

  //encodes src and copies that to dest
  static inline void default_conversion(hilbert_color &dest, const rgb24 &src) {
    dest = euler::syscall::encode_color(src.r, src.g, src.b);
  }

  template <class dest_t, class src_t, class param_t>
  using param_converter_t = void (dest_t &, const src_t &, const param_t &);

  //if src is true, copies param to dest.
  //if src is false, does nothing.
  template <class color_t>
  static inline void default_conversion(
    color_t &dest, const bool &src, const color_t &param) {
    if (src)
      dest = param;
  }

  //intersects [to, to + length) with [min, max) at stores the result in
  //[to, to + length). if anything was removed from either end, the same
  //amount is removed from the same end(s) of [from, from + length)
  static inline void make_safe(
    int &to, int &from, int &length, int min, int max) {

    if (to < min) {
      from += min - to;
      length -= min - to;
      to = min;
    }

    if (to + length > max)
      length = max - to;

  }

}
