text: module.exports = function ( grunt ) {
    
    /** 
     * Load required Grunt tasks. These are installed based on the versions listed
     * in `package.json` when you do `npm install` in this directory.
     */
    grunt.loadNpmTasks('grunt-contrib-clean');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-watch');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-coffee');
    grunt.loadNpmTasks('grunt-contrib-sass');
    grunt.loadNpmTasks('grunt-contrib-connect');
    grunt.loadNpmTasks('grunt-conventional-changelog');
    grunt.loadNpmTasks('grunt-bump');
    grunt.loadNpmTasks('grunt-coffeelint');
    grunt.loadNpmTasks('grunt-karma');
    grunt.loadNpmTasks('grunt-ngmin');
    grunt.loadNpmTasks('grunt-html2js');
  
    /**
     * Load in our build configuration file.
     */
    var userConfig = require( './build.config.js' );
  
    /**
     * This is the configuration object Grunt uses to give each plugin its 
     * instructions.
     */
    var taskConfig = {
      /**
       * We read in our `package.json` file so we can access the package name and
       * version. It's already there, so we don't repeat ourselves here.
       */
      pkg: grunt.file.readJSON("package.json"),
  
      /**
       * The banner is the comment that is placed at the top of our compiled 
       * source files. It is first processed as a Grunt template, where the `<%=`
       * pairs are evaluated based on this very configuration object.
       */
      meta: {
        banner: 
          '/**\n' +
          ' * <%= pkg.name %> - v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
          ' * <%= pkg.homepage %>\n' +
          ' *\n' +
          ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
          ' * Licensed <%= pkg.licenses.type %> <<%= pkg.licenses.url %>>\n' +
          ' */\n'
      },
  
      /**
       * Creates a changelog on a new version.
       */
      changelog: {
        options: {
          dest: 'CHANGELOG.md',
          template: 'changelog.tpl'
        }
      },
  
      /**
       * Increments the version number, etc.
       */
      bump: {
        options: {
          files: [
            "package.json", 
            "bower.json"
          ],
          commit: false,
          commitMessage: 'chore(release): v%VERSION%',
          commitFiles: [
            "package.json", 
            "client/bower.json"
          ],
          createTag: false,
          tagName: 'v%VERSION%',
          tagMessage: 'Version %VERSION%',
          push: false,
          pushTo: 'origin'
        }
      },    
  
      /**
       * The directories to delete when `grunt clean` is executed.
       */
      clean:{
        build: [
          '<%= build_dir %>', 
          '<%= compile_dir %>'
        ],
        js: [
          '<%= build_dir %>/src/**/*.js'
        ]
      },
  
      /**
       * The `copy` task just copies files from A to B. We use it here to copy
       * our project assets (images, fonts, etc.) and javascripts into
       * `build_dir`, and then to copy the assets to `compile_dir`.
       */
      copy: {
        build_app_assets: {
          files: [
            { 
              src: [ '**' ],
              dest: '<%= build_dir %>/assets/',
              cwd: 'src/assets',
              expand: true
            }
         ]   
        },
        build_vendor_assets: {
          files: [
            { 
              src: [ '<%= vendor_files.assets %>' ],
              dest: '<%= build_dir %>/assets/',
              cwd: '.',
              expand: true,
              flatten: true
            },
            {
                src: [ '<%= vendor_files.font %>' ],
                dest: '<%= build_dir %>/fonts/',
                flatten: true,
                cwd: '.',
                expand: true
            }
         ]
        },
        build_appjs: {
          files: [
            {
              src: [ '<%= app_files.js %>' ],
              dest: '<%= build_dir %>/',
              cwd: '.',
              expand: true
            }
          ]
        },
        build_vendorjs: {
          files: [
            {
              src: [ '<%= vendor_files.js %>' ],
              dest: '<%= build_dir %>/',
              cwd: '.',
              expand: true
            }
          ]
        },
        compile_assets: {
          files: [
            {
              src: [ '**' ],
              dest: '<%= compile_dir %>/assets',
              cwd: '<%= build_dir %>/assets',
              expand: true
            }
          ]
        }
      },
  
      /**
       * `grunt concat` concatenates multiple source files into a single file.
       */
      concat: {
        /**
         * The `build_css` target concatenates compiled CSS and vendor CSS
         * together.
         */
        build_css: {
          src: [
            '<%= vendor_files.css %>',
            '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'
          ],
          dest: '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'
        },
        /**
         * The `compile_js` target is the concatenation of our application source
         * code and all specified vendor source code into a single file.
         */
        compile_js: {
          options: {
            banner: '<%= meta.banner %>'
          },
          src: [ 
            '<%= vendor_files.js %>', 
            'module.prefix', 
            '<%= build_dir %>/src/**/*.js', 
            '<%= html2js.app.dest %>', 
            '<%= html2js.common.dest %>', 
            'module.suffix' 
          ],
          dest: '<%= compile_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.js'
        }
      },    
  
      /**
       * `grunt coffee` compiles the CoffeeScript sources. To work well with the
       * rest of the build, we have a separate compilation task for sources and
       * specs so they can go to different places. For example, we need the
       * sources to live with the rest of the copied JavaScript so we can include
       * it in the final build, but we don't want to include our specs there.
       */
      coffee: {
        source: {
          options: {
            bare: true
          },
          expand: true,
          cwd: '.',
          src: [ '<%= app_files.coffee %>' ],
          dest: '<%= build_dir %>',
          ext: '.js'
        }
      },
  
      /**
       * `ng-min` annotates the sources before minifying. That is, it allows us
       * to code without the array syntax.
       */
      ngmin: {
        compile: {
          files: [
            {
              src: [ '<%= app_files.js %>' ],
              cwd: '<%= build_dir %>',
              dest: '<%= build_dir %>',
              expand: true
            }
          ]
        }
      },
  
      /**
       * Minify the sources!
       */
      uglify: {
        compile: {
          options: {
            banner: '<%= meta.banner %>'
          },
          files: {
            '<%= concat.compile_js.dest %>': '<%= concat.compile_js.dest %>'
          }
        }
      },
  
      /**
       * `grunt-contrib-less` handles our LESS compilation and uglification automatically.
       * Only our `main.less` file is included in compilation; all other files
       * must be imported from this file.
       */
      // less: {
      //   build: {
      //     files: {
      //       '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css': '<%= app_files.less %>'
      //     }
      //   },
      //   compile: {
      //     files: {
      //       '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css': '<%= app_files.less %>'
      //     },
      //     options: {
      //       cleancss: true,
      //       compress: true
      //     }
      //   }
      // },
      
      sass: {
        build: {
          files: {
            '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css': '<%= app_files.sass %>'
          },
          options: {
            compass: true
            
          }
        },
        compile: {
          files: {
            '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css': '<%= app_files.sass %>'
          },
          options: {
            compass: true
  
          }
        }
      },
  
      /**
       * `jshint` defines the rules of our linter as well as which files we
       * should check. This file, all javascript sources, and all our unit tests
       * are linted based on the policies listed in `options`. But we can also
       * specify exclusionary patterns by prefixing them with an exclamation
       * point (!); this is useful when code comes from a third party but is
       * nonetheless inside `src/`.
       */
      jshint: {
        src: [ 
          '<%= app_files.js %>'
        ],
        test: [
          '<%= app_files.jsunit %>'
        ],
        gruntfile: [
          'Gruntfile.js'
        ],
        options: {
          curly: true,
          immed: true,
          newcap: true,
          noarg: true,
          sub: true,
          boss: true,
          eqnull: true
        },
        globals: {}
      },
  
      /**
       * `coffeelint` does the same as `jshint`, but for CoffeeScript.
       * CoffeeScript is not the default in ngBoilerplate, so we're just using
       * the defaults here.
       */
      coffeelint: {
        src: {
          files: {
            src: [ '<%= app_files.coffee %>' ]
          }
        },
        test: {
          files: {
            src: [ '<%= app_files.coffeeunit %>' ]
          }
        }
      },
  
      /**
       * HTML2JS is a Grunt plugin that takes all of your template files and
       * places them into JavaScript files as strings that are added to
       * AngularJS's template cache. This means that the templates too become
       * part of the initial payload as one JavaScript file. Neat!
       */
      html2js: {
        /**
         * These are the templates from `src/app`.
         */
        app: {
          options: {
            base: 'src/app'
          },
          src: [ '<%= app_files.atpl %>' ],
          dest: '<%= build_dir %>/templates-app.js'
        },
  
        /**
         * These are the templates from `src/common`.
         */
        common: {
          options: {
            base: 'src/common'
          },
          src: [ '<%= app_files.ctpl %>' ],
          dest: '<%= build_dir %>/templates-common.js'
        }
      },
  
      /**
       * The Karma configurations.
       */
      karma: {
        options: {
          configFile: '<%= build_dir %>/karma-unit.js'
        },
        unit: {
          port: 9019,
          background: true
        },
        continuous: {
          singleRun: true
        }
      },
  
      /**
       * The `index` task compiles the `index.html` file as a Grunt template. CSS
       * and JS files co-exist here but they get split apart later.
       */
      index: {
  
        /**
         * During development, we don't want to have wait for compilation,
         * concatenation, minification, etc. So to avoid these steps, we simply
         * add all script files directly to the `<head>` of `index.html`. The
         * `src` property contains the list of included files.
         */
        build: {
          dir: '<%= build_dir %>',
          src: [
            '<%= vendor_files.js %>',
            '<%= build_dir %>/src/**/*.js',
            '<%= html2js.common.dest %>',
            '<%= html2js.app.dest %>',
            '<%= vendor_files.css %>',
            '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'
          ]
        },
  
        /**
         * When it is time to have a completely compiled application, we can
         * alter the above to include only a single JavaScript and a single CSS
         * file. Now we're back!
         */
        compile: {
          dir: '<%= compile_dir %>',
          src: [
            '<%= concat.compile_js.dest %>',
            '<%= vendor_files.css %>',
            '<%= build_dir %>/assets/<%= pkg.name %>-<%= pkg.version %>.css'
          ]
        }
      },
  
      /**
       * This task compiles the karma template so that changes to its file array
       * don't have to be managed manually.
       */
      karmaconfig: {
        unit: {
          dir: '<%= build_dir %>',
          src: [ 
            '<%= vendor_files.js %>',
            '<%= html2js.app.dest %>',
            '<%= html2js.common.dest %>',
            '<%= test_files.js %>'
          ]
        }
      },
  
      /**
       * And for rapid development, we have a watch set up that checks to see if
       * any of the files listed below change, and then to execute the listed 
       * tasks when they do. This just saves us from having to type "grunt" into
       * the command-line every time we want to see what we're working on; we can
       * instead just leave "grunt watch" running in a background terminal. Set it
       * and forget it, as Ron Popeil used to tell us.
       *
       * But we don't need the same thing to happen for all the files. 
       */
      delta: {
        /**
         * By default, we want the Live Reload to work for all tasks; this is
         * overridden in some tasks (like this file) where browser resources are
         * unaffected. It runs by default on port 35729, which your browser
         * plugin should auto-detect.
         */
        options: {
          livereload: true,
          event: ['changed', 'added', 'deleted']
        },
  
        /**
         * When the Gruntfile changes, we just want to lint it. In fact, when
         * your Gruntfile changes, it will automatically be reloaded!
         */
        gruntfile: {
          files: 'Gruntfile.js',
          tasks: [ 'jshint:gruntfile' ],
          options: {
            livereload: false
          }
        },
  
        /**
         * When our JavaScript source files change, we want to run lint them and
         * run our unit tests.
         */
        jssrc: {
          files: [ 
            '<%= app_files.js %>'
          ],
          tasks: ['copy:build_appjs',  'jshint:src' ],
          options: {
            event: ['changed', 'added', 'deleted']
          }
        },
  
        /**
         * When our CoffeeScript source files change, we want to run lint them and
         * run our unit tests.
         */
        // coffeesrc: {
        //   files: [
        //     '<%= app_files.coffee %>'
        //   ],
        //   tasks: [ 'coffeelint:src', 'coffee:source', 'karma:unit:run', 'copy:build_appjs' ]
        // },
  
        /**
         * When assets are changed, copy them. Note that this will *not* copy new
         * files, so this is probably not very useful.
         */
        assets: {
          files: [ 
            'src/assets/**/*'
          ],
          tasks: [ 'copy:build_app_assets', 'copy:build_vendor_assets' ]
        },
  
        /**
         * When index.html changes, we need to compile it.
         */
        html: {
          files: [ '<%= app_files.html %>' ],
          tasks: [ 'index:build' ]
        },
  
        /**
         * When our templates change, we only rewrite the template cache.
         */
        tpls: {
          files: [ 
            '<%= app_files.atpl %>', 
            '<%= app_files.ctpl %>'
          ],
          tasks: [ 'html2js' ]
        },
  
        /**
         * When the CSS files change, we need to compile and minify them.
         */
        // less: {
        //   files: [ 'src/**/*.less' ],
        //   tasks: [ 'less:build' ]
        // },
  
        sass: {
          files: [ 'src/**/*.scss' ],
          tasks: [ 'sass:build' ]
        },
  
        /**
         * When a JavaScript unit test file changes, we only want to lint it and
         * run the unit tests. We don't want to do any live reloading.
         */
        jsunit: {
          files: [
            '<%= app_files.jsunit %>'
          ],
          tasks: [ 'jshint:test', 'karma:unit:run' ],
          options: {
            livereload: false
          }
        },
  
        /**
         * When a CoffeeScript unit test file changes, we only want to lint it and
         * run the unit tests. We don't want to do any live reloading.
         */
        // coffeeunit: {
        //   files: [
        //     '<%= app_files.coffeeunit %>'
        //   ],
        //   tasks: [ 'coffeelint:test', 'karma:unit:run' ],
        //   options: {
        //     livereload: false
        //   }
        // }
      },
  
      connect: {
        server: {
          options: {
            port: 8001,
            livereload: true,
            base: '<%= build_dir %>',
            hostname: '*',
            event: ['changed', 'added', 'deleted'],
  
            /* Support `$locationProvider.html5Mode(true);`
             * Requires grunt 0.9.0 or higher
             * Otherwise you will see this error:
             *   Running "connect:livereload" (connect) task
             *   Warning: Cannot call method 'push' of undefined Use --force to continue.
             */
            middleware: function (connect, options, middlewares) {
              var modRewrite = require('connect-modrewrite');
  
              // enable Angular's HTML5 mode
              middlewares.unshift(modRewrite(['!\\.html|\\.js|\\.svg|\\.css|\\.png|\\.jpg|\\.jpeg|\\.ttf|\\.json|\\.woff|\\.eot|\\.mp3|\\.waw|\\.webm|\\.woff2$ /index.html [L]']));
  
              return middlewares;
            },
  
            protocol: "http"
  
          }
        }
      }
    };
  
    grunt.initConfig( grunt.util._.extend( taskConfig, userConfig ) );
  
    /**
     * In order to make it safe to just compile or copy *only* what was changed,
     * we need to ensure we are starting from a clean, fresh build. So we rename
     * the `watch` task to `delta` (that's why the configuration var above is
     * `delta`) and then add a new task called `watch` that does a clean build
     * before watching for changes.
     */
    grunt.renameTask( 'watch', 'delta' );
    grunt.registerTask( 'watch', ['clean:build', 'build', /*'karma:unit',*/ 'connect:server', 'delta'] );
  
    /**
     * The default task is to build and compile.
     */
    grunt.registerTask( 'default', [ 'build', 'compile' ] );
  
    /**
     * The `build` task gets your app ready to run for development and testing.
     */
    grunt.registerTask( 'build', [
      'clean:build', 'html2js', 'jshint', 'coffeelint', 'coffee', 'sass:build',
      'concat:build_css', 'copy:build_app_assets', 'copy:build_vendor_assets',
      'copy:build_appjs', 'copy:build_vendorjs', 'index:build'//, 'karmaconfig',
      //'karma:continuous' 
    ]);
  
    /**
     * The `compile` task gets your app ready for deployment by concatenating and
     * minifying your code.
     */
    grunt.registerTask( 'compile', [
      'sass:compile', 'copy:compile_assets', 'ngmin', 'concat:compile_js', 'uglify', 'index:compile'
    ]);
  
    /**
     * A utility function to get all app JavaScript sources.
     */
    function filterForJS ( files ) {
      return files.filter( function ( file ) {
        return file.match( /\.js$/ );
      });
    }
  
    /**
     * A utility function to get all app CSS sources.
     */
    function filterForCSS ( files ) {
      return files.filter( function ( file ) {
        return file.match( /\.css$/ );
      });
    }
  
    /** 
     * The index.html template includes the stylesheet and javascript sources
     * based on dynamic names calculated in this Gruntfile. This task assembles
     * the list into variables for the template to use and then runs the
     * compilation.
     */
    grunt.registerMultiTask( 'index', 'Process index.html template', function () {
      var dirRE = new RegExp( '^('+grunt.config('build_dir')+'|'+grunt.config('compile_dir')+')\/', 'g' );
      var jsFiles = filterForJS( this.filesSrc ).map( function ( file ) {
        return file.replace( dirRE, '' );
      });
      var cssFiles = filterForCSS( this.filesSrc ).map( function ( file ) {
        return file.replace( dirRE, '' );
      });
  
      grunt.file.copy('src/index.html', this.data.dir + '/index.html', { 
        process: function ( contents, path ) {
          return grunt.template.process( contents, {
            data: {
              scripts: jsFiles,
              styles: cssFiles,
              version: grunt.config( 'pkg.version' )
            }
          });
        }
      });
      grunt.file.copy('src/sitemap.xml', this.data.dir + '/sitemap.xml', {
      });
    });
  
    /**
     * In order to avoid having to specify manually the files needed for karma to
     * run, we use grunt to manage the list for us. The `karma/*` files are
     * compiled as grunt templates for use by Karma. Yay!
     */
    grunt.registerMultiTask( 'karmaconfig', 'Process karma config templates', function () {
      var jsFiles = filterForJS( this.filesSrc );
      
      grunt.file.copy( 'karma/karma-unit.tpl.js', grunt.config( 'build_dir' ) + '/karma-unit.js', { 
        process: function ( contents, path ) {
          return grunt.template.process( contents, {
            data: {
              scripts: jsFiles
            }
          });
        }
      });
    });
  
  };
  