{ nixpkgs ? import <nixpkgs> {}, compiler ? "default", doBenchmark ? false }:

let

  inherit (nixpkgs) pkgs;

  #provideOldHaskellAttributeNames = true;

  glib = with haskellPackages; callPackage(
    { mkDerivation, base, bytestring, Cabal, containers, glib
    , stdenv, text, utf8-string
    }:
    mkDerivation {
      pname = "glib";
      version = "0.13.6.0";
      sha256 = "4e71062c6a458440294d820e21449aa4666deed2ea233ef5915da7c1d4aee8eb";
      setupHaskellDepends = [ base Cabal gtk2hs-buildtools ];
      libraryHaskellDepends = [
        base bytestring containers text utf8-string
      ];
      libraryPkgconfigDepends = [ pkgs.glib ];
      homepage = "http://projects.haskell.org/gtk2hs/";
      description = "Binding to the GLIB library for Gtk2Hs";
      license = stdenv.lib.licenses.lgpl21;
    }) {};

  gtk2hs-buildtools = with haskellPackages; callPackage(
    { mkDerivation, alex, array, base, Cabal, containers, directory
    , filepath, happy, hashtables, pretty, process, random, stdenv
    }:
    mkDerivation {
      pname = "gtk2hs-buildtools";
      version = "0.13.4.0";
      src = ../gtk2hs/tools;
      isLibrary = true;
      isExecutable = true;
      enableSeparateDataOutput = true;
      libraryHaskellDepends = [
        array base Cabal containers directory filepath hashtables pretty
        process random
      ];
      libraryToolDepends = [ alex happy ];
      executableHaskellDepends = [ base ];
      homepage = "http://projects.haskell.org/gtk2hs/";
      description = "Tools to build the Gtk2Hs suite of User Interface libraries";
      license = stdenv.lib.licenses.gpl2;
    }) {};

  cereal = with haskellPackages; callPackage(
    { mkDerivation, array, base, bytestring, containers, ghc-prim
    , QuickCheck, stdenv, test-framework, test-framework-quickcheck2
    }:
    mkDerivation {
      pname = "cereal";
      version = "0.5.7.0";
      sha256 = "7abdaf6d52260e714adcf1c3e16f2e25a56492d90a747d1a9594e15f05acf1c8";
      libraryHaskellDepends = [
        array base bytestring containers ghc-prim
      ];
      testHaskellDepends = [
        base bytestring QuickCheck test-framework
        test-framework-quickcheck2
      ];
      homepage = "https://github.com/GaloisInc/cereal";
      description = "A binary serialization library";
      license = stdenv.lib.licenses.bsd3;
      doCheck = false;
    }) {};

  linear = with haskellPackages; callPackage(
    { mkDerivation, adjunctions, base, base-orphans, binary
    , bytestring, Cabal, cabal-doctest, containers, deepseq
    , distributive, doctest, ghc-prim, hashable, HUnit, lens
    , reflection, semigroupoids, semigroups, simple-reflect, stdenv
    , tagged, template-haskell, test-framework, test-framework-hunit
    , transformers, transformers-compat, unordered-containers, vector
    , void
    }:
    mkDerivation {
      pname = "linear";
      version = "1.20.8";
      sha256 = "5ebd1b99837f2e3c7386bcd2ca425d9c66b09a61409792b141428345fb9edb10";
      setupHaskellDepends = [ base Cabal cabal-doctest ];
      libraryHaskellDepends = [
        adjunctions base base-orphans binary bytes cereal containers
        deepseq distributive ghc-prim hashable lens reflection
        semigroupoids semigroups tagged template-haskell transformers
        transformers-compat unordered-containers vector void
      ];
      testHaskellDepends = [
        base binary bytestring deepseq doctest HUnit lens reflection
        simple-reflect test-framework test-framework-hunit vector
      ];
      homepage = "http://github.com/ekmett/linear/";
      description = "Linear Algebra";
      license = stdenv.lib.licenses.bsd3;
    }) {};

  bytes = with haskellPackages; callPackage(
    { mkDerivation, base, binary, bytestring, Cabal, cabal-doctest
    , containers, directory, doctest, filepath, hashable, mtl
    , scientific, stdenv, text, time, transformers, transformers-compat
    , unordered-containers, void
    }:
    mkDerivation {
      pname = "bytes";
      version = "0.15.5";
      sha256 = "039935e6b367eb8657aa3eb109e719b257a06524b0d9ff5246e8029bb7a07118";
      setupHaskellDepends = [ base Cabal cabal-doctest ];
      libraryHaskellDepends = [
        base binary bytestring cereal containers hashable mtl scientific
        text time transformers transformers-compat unordered-containers
        void
      ];
      testHaskellDepends = [ base directory doctest filepath ];
      homepage = "https://github.com/ekmett/bytes";
      description = "Sharing code for serialization between binary and cereal";
      license = stdenv.lib.licenses.bsd3;
    }) {};

  aff = with haskellPackages; callPackage(
    { mkDerivation, base, bytestring, clock, containers, fetchgit
    , monad-loops, monad-parallel, mtl, OpenGL, stdenv, stm
    , text, uuid, vector
    }:
    mkDerivation {
      pname = "affection";
      version = "0.0.0.9";
      src = fetchgit {
        url = "https://github.com/nek0/affection";
        sha256 = "08pf1nqha62m608zmcyyshljzga8h1p9hyxvwrk4affsaj7vpkpx";
        rev = "91c70c6ec62e407bd6d0233fbc2c64bafc3b6cdc";
        fetchSubmodules = true;
      };
      configureFlags = [ "-fdebug" ];
      isLibrary = true;
      isExecutable = true;
      libraryHaskellDepends = [
        base bytestring clock containers glib linear monad-loops
        monad-parallel mtl OpenGL sdl stm uuid text vector
      ];
      homepage = "https://github.com/nek0/affection#readme";
      description = "A simple Game Engine using SDL";
      license = stdenv.lib.licenses.lgpl3;
    }) {};

  psq = with haskellPackages; callPackage(
    { mkDerivation, array, base, containers, criterion, deepseq
    , fingertree-psqueue, ghc-prim, hashable, HUnit, mtl, PSQueue
    , QuickCheck, random, stdenv, tagged, test-framework
    , test-framework-hunit, test-framework-quickcheck2
    , unordered-containers
    }:
    mkDerivation {
      pname = "psqueues";
      version = "0.2.7.0";
      sha256 = "4cf3628884015b091471e4425f5414207fd547cf71d9546e9b7318d857624fea";
      libraryHaskellDepends = [ base deepseq ghc-prim hashable ];
      testHaskellDepends = [
        array base deepseq ghc-prim hashable HUnit QuickCheck tagged
        test-framework test-framework-hunit test-framework-quickcheck2
      ];
      benchmarkHaskellDepends = [
        base containers criterion deepseq fingertree-psqueue ghc-prim
        hashable mtl PSQueue random unordered-containers
      ];
      description = "Pure priority search queues";
      license = stdenv.lib.licenses.bsd3;
      doCheck = false;
    }) {};

  astar = with haskellPackages; callPackage(
    { mkDerivation, base, hashable, stdenv
    , unordered-containers
    }:
    mkDerivation {
      pname = "astar";
      version = "0.3.0.0";
      sha256 = "2117c007d5daa88401a49c994b8e3361ddae331d458b1a403fac2a4f304b9b87";
      libraryHaskellDepends = [
        base hashable psq unordered-containers
      ];
      homepage = "https://github.com/weissi/astar";
      description = "General A* search algorithm";
      license = stdenv.lib.licenses.bsd3;
    }) {};

  sdl = with haskellPackages; callPackage(
    { mkDerivation, base, bytestring, deepseq, exceptions
    , StateVar, stdenv, text, transformers, vector, weigh, pkgconfig
    }:
    mkDerivation {
      pname = "sdl2";
      version = "2.4.1.0";
      sha256 = "21a569c0c19f8ff2bbe1cf1d3eb32f65e8143806de353cedd240df5e9d088b5c";
      isLibrary = true;
      isExecutable = true;
      enableSeparateDataOutput = true;
      libraryHaskellDepends = [
        base bytestring exceptions linear StateVar text transformers vector
      ];
      buildDepends = [ pkgconfig ];
      librarySystemDepends = [ nixpkgs.SDL2 pkgconfig ];
      libraryPkgconfigDepends = [ nixpkgs.SDL2 pkgconfig ];
      testHaskellDepends = [ base deepseq linear vector weigh ];
      doCheck = false;
      description = "Both high- and low-level bindings to the SDL library (version 2.0.4+).";
      license = stdenv.lib.licenses.bsd3;
    }) {};

  nano = with haskellPackages; callPackage(
    { mkDerivation, base, bytestring, c2hs, containers, fetchgit
    , glew, hspec, inline-c, libGL, libGLU, QuickCheck, stdenv, text
    , vector
    }:
    mkDerivation {
      pname = "nanovg";
      version = "0.6.0.0";
      src = ../nanovg-hs;
      isLibrary = true;
      isExecutable = true;
      libraryHaskellDepends = [ base bytestring containers text vector ];
      librarySystemDepends = [ glew libGL libGLU ];
      libraryPkgconfigDepends = [ glew ];
      libraryToolDepends = [ c2hs ];
      testHaskellDepends = [ base containers hspec inline-c QuickCheck ];
      homepage = "https://github.com/cocreature/nanovg-hs";
      description = "Haskell bindings for nanovg";
      doCheck = false;
      license = stdenv.lib.licenses.isc;
    }) {};

  f = { mkDerivation, algebraic-graphs, base
      , bytestring, containers, ecstasy, JuicyPixels, JuicyPixels-extra
      , matrix, mtl, OpenGL, random, stdenv, stm, split
      , text, unordered-containers, vector, pkgconfig
      }:
      mkDerivation {
        pname = "tracer-game";
        version = "0.0.0.0";
        src = ./.;
        isLibrary = false;
        isExecutable = true;
        executableHaskellDepends = [
          aff algebraic-graphs astar base bytestring containers ecstasy
          JuicyPixels JuicyPixels-extra linear matrix mtl nano OpenGL
          random sdl stm split text unordered-containers vector pkgconfig
        ];
        enableExecutableProfiling = true;
        enableLibraryProfiling = true;
        license = stdenv.lib.licenses.gpl3;
      };

  haskellPackages = if compiler == "default"
                       then pkgs.haskellPackages
                       else pkgs.haskell.packages.${compiler};

  variant = if doBenchmark then pkgs.haskell.lib.doBenchmark else pkgs.lib.id;

  drv = variant (haskellPackages.callPackage f {});

in

  if pkgs.lib.inNixShell then drv.env else drv
