/*eslint-env node */

let zipUtils = require('./tools/modules/zip-helper');
let gruntUtils = require('./tools/modules/grunt-utils');
let gruntWebPack = require('./tools/modules/grunt-webpack');
let swag = require('@ephox/swag');
let path = require('path');

let plugins = [
  'advlist', 'anchor', 'autolink', 'autoresize', 'autosave', 'bbcode', 'charmap', 'code', 'codesample',
  'colorpicker', /*'compat3x', */ 'contextmenu', 'directionality', 'emoticons', 'help', 'fullpage',
  'fullscreen', 'hr', 'image', 'imagetools', 'importcss', 'insertdatetime', 'legacyoutput', 'link',
  'lists', 'media', 'nonbreaking', 'noneditable', 'pagebreak', 'paste', 'preview', 'print', 'save',
  'searchreplace', 'spellchecker', 'tabfocus', 'table', 'template', 'textcolor', 'textpattern', 'toc',
  'visualblocks', 'visualchars', 'wordcount',
];

let themes = [
  'modern', 'mobile', 'inlite'
];

module.exports = function (grunt) {
  var packageData = grunt.file.readJSON('package.json');
  var changelogLine = grunt.file.read('changelog.txt').toString().split('\n')[0];
  var BUILD_VERSION = packageData.version + '-' + (process.env.BUILD_NUMBER ? process.env.BUILD_NUMBER : '0');
  packageData.date = /^Version [^\(]+\(([^\)]+)\)/.exec(changelogLine)[1];

  grunt.initConfig({
    pkg: packageData,

    shell: {
      tsc: { command: 'node ./node_modules/typescript/bin/tsc' }
    },

    tslint: {
      options: {
        configuration: 'tslint.json'
      },
      files: { src: [ 'src/**/*.ts' ] }
    },

    globals: {
      options: {
        configFile: 'src/core/main/json/globals.json',
        outputDir: 'lib/globals',
        templateFile: 'src/core/main/js/GlobalsTemplate.js'
      }
    },

    rollup: Object.assign(
      {
        core: {
          options: {
            treeshake: true,
            name: 'tinymce',
            format: 'iife',
            banner: '(function () {',
            footer: '})();',
            onwarn: swag.onwarn,
            plugins: [
              swag.nodeResolve({
                basedir: __dirname,
                prefixes: {
                  'tinymce/core': 'lib/core/main/ts'
                }
              }),
              swag.remapImports()
            ]
          },
          files:[
            {
              src: 'lib/core/main/ts/api/Main.js',
              dest: 'js/tinymce/tinymce.js'
            }
          ]
        }
      },
      gruntUtils.generate(plugins, 'plugin', (name) => {
        return {
          options: {
            treeshake: true,
            name: name,
            format: 'iife',
            banner: '(function () {',
            footer: '})();',
            onwarn: swag.onwarn,
            plugins: [
              swag.nodeResolve({
                basedir: __dirname,
                prefixes: gruntUtils.prefixes({
                  'tinymce/core': 'lib/globals/tinymce/core'
                }, [
                  [`tinymce/plugins/${name}`, `lib/plugins/${name}/main/ts`]
                ]),
                mappers: [
                  swag.mappers.replaceDir('./lib/core/main/ts/api', './lib/globals/tinymce/core/api'),
                  swag.mappers.invalidDir('./lib/core/main/ts')
                ]
              }),
              swag.remapImports()
            ]
          },
          files:[ { src: `lib/plugins/${name}/main/ts/Plugin.js`, dest: `js/tinymce/plugins/${name}/plugin.js` } ]
        };
      }),
      gruntUtils.generate(themes, 'theme', (name) => {
        return {
          options: {
            treeshake: true,
            name: name,
            format: 'iife',
            banner: '(function () {',
            footer: '})();',
            onwarn: swag.onwarn,
            plugins: [
              swag.nodeResolve({
                basedir: __dirname,
                prefixes: gruntUtils.prefixes({
                  'tinymce/core': 'lib/globals/tinymce/core',
                  'tinymce/ui': 'lib/ui/main/ts'
                }, [
                  [`tinymce/themes/${name}`, `lib/themes/${name}/main/ts`]
                ]),
                mappers: [
                  swag.mappers.replaceDir('./lib/core/main/ts/api', './lib/globals/tinymce/core/api'),
                  swag.mappers.invalidDir('./lib/core/main/ts')
                ]
              }),
              swag.remapImports()
            ]
          },
          files:[
            {
              src: `lib/themes/${name}/main/ts/Theme.js`,
              dest: `js/tinymce/themes/${name}/theme.js`
            }
          ]
        };
      })
    ),

    uglify: Object.assign(
      {
        options: {
          output: {
            ascii_only: true,
          },
          ie8: true
        },
        core: {
          files: [
            { src: 'js/tinymce/tinymce.js', dest: 'js/tinymce/tinymce.min.js' },
            { src: 'src/core/main/js/JqueryIntegration.js', dest: 'js/tinymce/jquery.tinymce.min.js' }
          ]
        },
        'compat3x-plugin': {
          files: [
            {
              src: 'src/plugins/compat3x/main/js/plugin.js',
              dest: 'js/tinymce/plugins/compat3x/plugin.min.js'
            }
          ]
        }
      },
      gruntUtils.generate(plugins, 'plugin', (name) => {
        return {
          files: [ { src: `js/tinymce/plugins/${name}/plugin.js`, dest: `js/tinymce/plugins/${name}/plugin.min.js` } ]
        };
      }),
      gruntUtils.generate(themes, 'theme', (name) => {
        return {
          files: [ { src: `js/tinymce/themes/${name}/theme.js`, dest: `js/tinymce/themes/${name}/theme.min.js` } ]
        };
      })
    ),

    webpack: Object.assign(
      {core: () => gruntWebPack.create('src/core/demo/ts/demo/Demos.ts', 'tsconfig.json', 'scratch/demos/core', 'demo.js')},
      {plugins: () => gruntWebPack.allPlugins(plugins)},
      {themes: () => gruntWebPack.allThemes(themes)},
      gruntUtils.generate(plugins, 'plugin', (name) => () => gruntWebPack.createPlugin(name) ),
      gruntUtils.generate(themes, 'theme', (name) => () => gruntWebPack.createTheme(name) )
    ),

    'webpack-dev-server': {
      options: {
        webpack: gruntWebPack.all(plugins, themes),
        publicPath: '/',
        inline: false,
        port: grunt.option('webpack-port') !== undefined ? grunt.option('webpack-port') : 3000,
        host: '0.0.0.0',
        disableHostCheck: true,
        before: app => gruntWebPack.generateDemoIndex(grunt, app, plugins, themes)
      },
      start: { }
    },

    less: {
      desktop: {
        options: {
          cleancss: true,
          strictImports: true,
          compress: true,
          yuicompress: true,
          sourceMap: true,
          sourceMapRootpath: '.',
          optimization: 2
        },
        files: {
          'js/tinymce/skins/lightgray/skin.min.css': 'src/skins/lightgray/main/less/desktop/Skin.less'
        }
      },
      mobile: {
        options: {
          plugins : [ new (require('less-plugin-autoprefix'))({ browsers : [ 'last 2 versions', /* for phantom */'safari >= 4' ] }) ],
          compress: true,
          yuicompress: true,
          sourceMap: true,
          sourceMapRootpath: '.',
          optimization: 2
        },
        files: {
          'js/tinymce/skins/lightgray/skin.mobile.min.css': 'src/skins/lightgray/main/less/mobile/app/mobile-less.less'
        }
      },
      'content-mobile': {
        options: {
          cleancss: true,
          strictImports: true,
          compress: true
        },
        files: {
          'js/tinymce/skins/lightgray/content.mobile.min.css': 'src/skins/lightgray/main/less/mobile/content.less'
        }
      },
      content: {
        options: {
          cleancss: true,
          strictImports: true,
          compress: true
        },
        files: {
          'js/tinymce/skins/lightgray/content.min.css': 'src/skins/lightgray/main/less/desktop/Content.less'
        }
      },
      'content-inline': {
        options: {
          cleancss: true,
          strictImports: true,
          compress: true
        },
        files: {
          'js/tinymce/skins/lightgray/content.inline.min.css': 'src/skins/lightgray/main/less/desktop/Content.Inline.less'
        }
      }
    },

    copy: {
      core: {
        options: {
          process: function (content) {
            return content.
              replace('@@majorVersion@@', packageData.version.split('.')[0]).
              replace('@@minorVersion@@', packageData.version.split('.').slice(1).join('.')).
              replace('@@releaseDate@@', packageData.date);
          }
        },
        files: [
          {
            src: 'js/tinymce/tinymce.js',
            dest: 'js/tinymce/tinymce.js'
          },
          {
            src: 'js/tinymce/tinymce.min.js',
            dest: 'js/tinymce/tinymce.min.js'
          },
          {
            src: 'src/core/main/text/readme_lang.md',
            dest: 'js/tinymce/langs/readme.md'
          },
          {
            src: 'LICENSE.TXT',
            dest: 'js/tinymce/license.txt'
          }
        ]
      },
      skins: {
        files: [
          {
            expand: true,
            flatten: true,
            cwd: 'src/skins/lightgray/main/fonts',
            src: [
              '**',
              '!*.json',
              '!*.md'
            ],
            dest: 'js/tinymce/skins/lightgray/fonts'
          },
          {
            expand: true,
            flatten: true,
            cwd: 'src/skins/lightgray/main/img',
            src: '**',
            dest: 'js/tinymce/skins/lightgray/img'
          }
        ]
      },
      plugins: {
        files: [
          { expand: true, cwd: 'src/plugins/compat3x/main', src: ['img/**'], dest: 'js/tinymce/plugins/compat3x' },
          { expand: true, cwd: 'src/plugins/compat3x/main', src: ['css/**'], dest: 'js/tinymce/plugins/compat3x' },
          { expand: true, cwd: 'src/plugins/compat3x/main/js', src: ['utils/**', 'plugin.js', 'tiny_mce_popup.js'], dest: 'js/tinymce/plugins/compat3x' },
          { src: 'src/plugins/codesample/main/css/prism.css', dest: 'js/tinymce/plugins/codesample/css/prism.css' }
        ]
      },
      'emoticons-plugin': {
        files: [
          {
            flatten: true,
            expand: true,
            cwd: 'src/plugins/emoticons/main/img',
            src: '*.gif',
            dest: 'js/tinymce/plugins/emoticons/img/'
          }
        ]
      },
      'help-plugin': {
        files: [
          { src: 'src/plugins/help/main/img/logo.png', dest: 'js/tinymce/plugins/help/img/logo.png' }
        ]
      },
      'visualblocks-plugin': {
        files: [
          { src: 'src/plugins/visualblocks/main/css/visualblocks.css', dest: 'js/tinymce/plugins/visualblocks/css/visualblocks.css' }
        ]
      }
    },

    moxiezip: {
      production: {
        options: {
          baseDir: 'tinymce',
          excludes: [
            'js/**/plugin.js',
            'js/**/theme.js',
            'js/**/*.map',
            'js/tinymce/tinymce.full.min.js',
            'js/tinymce/plugins/moxiemanager',
            'js/tinymce/plugins/compat3x',
            'js/tinymce/plugins/visualblocks/img',
            'js/tinymce/skins/*/fonts/*.json',
            'js/tinymce/skins/*/fonts/readme.md',
            'readme.md'
          ],
          to: 'tmp/tinymce_<%= pkg.version %>.zip'
        },
        src: [
          'js/tinymce/langs',
          'js/tinymce/plugins',
          'js/tinymce/skins',
          'js/tinymce/themes',
          'js/tinymce/tinymce.min.js',
          'js/tinymce/jquery.tinymce.min.js',
          'js/tinymce/license.txt',
          'changelog.txt',
          'LICENSE.TXT',
          'readme.md'
        ]
      },

      development: {
        options: {
          baseDir: 'tinymce',
          excludes: [
            'src/**/dist',
            'src/**/scratch',
            'src/**/lib',
            'src/**/dependency',
            'js/tinymce/tinymce.full.min.js',
            'js/tests/.jshintrc'
          ],
          to: 'tmp/tinymce_<%= pkg.version %>_dev.zip'
        },
        src: [
          'config',
          'src',
          'js',
          'tests',
          'tools',
          'changelog.txt',
          'LICENSE.TXT',
          'Gruntfile.js',
          'readme.md',
          'package.json',
          '.eslintrc',
          '.jscsrc',
          '.jshintrc'
        ]
      },
      cdn: {
        options: {
          onBeforeSave: function (zip) {
            zip.addData('dist/version.txt', packageData.version);
          },
          pathFilter: function (zipFilePath) {
            return zipFilePath.replace('js/tinymce/', 'dist/');
          },
          excludes: [
            'js/**/config',
            'js/**/scratch',
            'js/**/classes',
            'js/**/lib',
            'js/**/dependency',
            'js/**/src',
            'js/**/*.less',
            'js/**/*.dev.js',
            'js/**/*.dev.svg',
            'js/**/*.map',
            'js/tinymce/tinymce.full.min.js',
            'js/tinymce/plugins/moxiemanager',
            'js/tinymce/plugins/visualblocks/img',
            'js/tinymce/skins/*/fonts/*.json',
            'js/tinymce/skins/*/fonts/*.dev.svg',
            'js/tinymce/skins/*/fonts/readme.md',
            'readme.md',
            'js/tests/.jshintrc'
          ],
          concat: [
            {
              src: [
                'js/tinymce/tinymce.min.js',
                'js/tinymce/themes/*/theme.min.js',
                'js/tinymce/plugins/*/plugin.min.js',
                '!js/tinymce/plugins/compat3x/plugin.min.js',
                '!js/tinymce/plugins/example/plugin.min.js',
                '!js/tinymce/plugins/example_dependency/plugin.min.js'
              ],

              dest: [
                'js/tinymce/tinymce.min.js'
              ]
            }
          ],
          to: 'tmp/tinymce_<%= pkg.version %>_cdn.zip'
        },
        src: [
          'js/tinymce/jquery.tinymce.min.js',
          'js/tinymce/tinymce.js',
          'js/tinymce/langs',
          'js/tinymce/plugins',
          'js/tinymce/skins',
          'js/tinymce/themes',
          'js/tinymce/license.txt'
        ]
      },

      component: {
        options: {
          excludes: [
            'js/**/config',
            'js/**/scratch',
            'js/**/classes',
            'js/**/lib',
            'js/**/dependency',
            'js/**/src',
            'js/**/*.less',
            'js/**/*.dev.svg',
            'js/**/*.dev.js',
            'js/**/*.map',
            'js/tinymce/tinymce.full.min.js',
            'js/tinymce/plugins/moxiemanager',
            'js/tinymce/plugins/example',
            'js/tinymce/plugins/example_dependency',
            'js/tinymce/plugins/compat3x',
            'js/tinymce/plugins/visualblocks/img',
            'js/tinymce/skins/*/fonts/*.json',
            'js/tinymce/skins/*/fonts/readme.md'
          ],
          pathFilter: function (zipFilePath) {
            if (zipFilePath.indexOf('js/tinymce/') === 0) {
              return zipFilePath.substr('js/tinymce/'.length);
            }

            return zipFilePath;
          },
          onBeforeSave: function (zip) {
            function jsonToBuffer(json) {
              return new Buffer(JSON.stringify(json, null, '\t'));
            }

            zip.addData('bower.json', jsonToBuffer({
              'name': 'tinymce',
              'description': 'Web based JavaScript HTML WYSIWYG editor control.',
              'license': 'LGPL-2.1',
              'keywords': ['editor', 'wysiwyg', 'tinymce', 'richtext', 'javascript', 'html'],
              'homepage': 'http://www.tinymce.com',
              'ignore': ['readme.md', 'composer.json', 'package.json', '.npmignore', 'changelog.txt']
            }));

            zip.addData('package.json', jsonToBuffer({
              'name': 'tinymce',
              'version': packageData.version,
              'repository': {
                'type': 'git',
                'url': 'https://github.com/tinymce/tinymce-dist.git'
              },
              'description': 'Web based JavaScript HTML WYSIWYG editor control.',
              'author': 'Ephox Corporation',
              'main': 'tinymce.js',
              'license': 'LGPL-2.1',
              'keywords': ['editor', 'wysiwyg', 'tinymce', 'richtext', 'javascript', 'html'],
              'bugs': { 'url': 'https://github.com/tinymce/tinymce/issues' }
            }));

            zip.addData('composer.json', jsonToBuffer({
              'name': 'tinymce/tinymce',
              'version': packageData.version,
              'description': 'Web based JavaScript HTML WYSIWYG editor control.',
              'license': ['LGPL-2.1-only'],
              'keywords': ['editor', 'wysiwyg', 'tinymce', 'richtext', 'javascript', 'html'],
              'homepage': 'http://www.tinymce.com',
              'type': 'component',
              'extra': {
                'component': {
                  'scripts': [
                    'tinymce.js',
                    'plugins/*/plugin.js',
                    'themes/*/theme.js'
                  ],
                  'files': [
                    'tinymce.min.js',
                    'plugins/*/plugin.min.js',
                    'themes/*/theme.min.js',
                    'skins/**'
                  ]
                }
              },
              'archive': {
                'exclude': ['readme.md', 'bower.js', 'package.json', '.npmignore', 'changelog.txt']
              }
            }));

            zip.addFile(
              'jquery.tinymce.js',
              'js/tinymce/jquery.tinymce.min.js'
            );

            var getDirs = zipUtils.getDirectories(grunt, this.excludes);

            zipUtils.addIndexFiles(
              zip,
              getDirs('js/tinymce/plugins'),
              zipUtils.generateIndex('plugins', 'plugin')
            );
            zipUtils.addIndexFiles(
              zip,
              getDirs('js/tinymce/themes'),
              zipUtils.generateIndex('themes', 'theme')
            );
          },
          to: 'tmp/tinymce_<%= pkg.version %>_component.zip'
        },
        src: [
          'js/tinymce/skins',
          'js/tinymce/plugins',
          'js/tinymce/themes',
          'js/tinymce/tinymce.js',
          'js/tinymce/tinymce.min.js',
          'js/tinymce/jquery.tinymce.min.js',
          'js/tinymce/license.txt',
          'changelog.txt',
          'readme.md'
        ]
      }
    },

    nugetpack: {
      main: {
        options: {
          id: 'TinyMCE',
          version: packageData.version,
          authors: 'Ephox Corp',
          owners: 'Ephox Corp',
          description: 'The best WYSIWYG editor! TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor ' +
          'control released as Open Source under LGPL by Ephox Corp. TinyMCE has the ability to convert HTML ' +
          'TEXTAREA fields or other HTML elements to editor instances. TinyMCE is very easy to integrate ' +
          'into other Content Management Systems.',
          releaseNotes: 'Release notes for my package.',
          summary: 'TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor ' +
          'control released as Open Source under LGPL by Ephox Corp.',
          projectUrl: 'http://www.tinymce.com/',
          iconUrl: 'http://www.tinymce.com/favicon.ico',
          licenseUrl: 'http://www.tinymce.com/license',
          requireLicenseAcceptance: true,
          tags: 'Editor TinyMCE HTML HTMLEditor',
          excludes: [
            'js/**/config',
            'js/**/scratch',
            'js/**/classes',
            'js/**/lib',
            'js/**/dependency',
            'js/**/src',
            'js/**/*.less',
            'js/**/*.dev.svg',
            'js/**/*.dev.js',
            'js/**/*.map',
            'js/tinymce/tinymce.full.min.js'
          ],
          outputDir: 'tmp'
        },
        files: [
          { src: 'js/tinymce/langs', dest: '/content/scripts/tinymce/langs' },
          { src: 'js/tinymce/plugins', dest: '/content/scripts/tinymce/plugins' },
          { src: 'js/tinymce/themes', dest: '/content/scripts/tinymce/themes' },
          { src: 'js/tinymce/skins', dest: '/content/scripts/tinymce/skins' },
          { src: 'js/tinymce/tinymce.js', dest: '/content/scripts/tinymce/tinymce.js' },
          { src: 'js/tinymce/tinymce.min.js', dest: '/content/scripts/tinymce/tinymce.min.js' },
          { src: 'js/tinymce/jquery.tinymce.min.js', dest: '/content/scripts/tinymce/jquery.tinymce.min.js' },
          { src: 'js/tinymce/license.txt', dest: '/content/scripts/tinymce/license.txt' }
        ]
      },

      jquery: {
        options: {
          id: 'TinyMCE.jQuery',
          title: 'TinyMCE.jQuery [Deprecated]',
          version: packageData.version,
          authors: 'Ephox Corp',
          owners: 'Ephox Corp',
          description: 'This package has been deprecated use https://www.nuget.org/packages/TinyMCE/',
          releaseNotes: 'This package has been deprecated use https://www.nuget.org/packages/TinyMCE/',
          summary: 'This package has been deprecated use https://www.nuget.org/packages/TinyMCE/',
          projectUrl: 'http://www.tinymce.com/',
          iconUrl: 'http://www.tinymce.com/favicon.ico',
          licenseUrl: 'http://www.tinymce.com/license',
          requireLicenseAcceptance: true,
          tags: 'Editor TinyMCE HTML HTMLEditor',
          excludes: [
            'js/**/config',
            'js/**/scratch',
            'js/**/classes',
            'js/**/lib',
            'js/**/dependency',
            'js/**/src',
            'js/**/*.less',
            'js/**/*.dev.svg',
            'js/**/*.dev.js',
            'js/**/*.map',
            'js/tinymce/tinymce.full.min.js'
          ],
          outputDir: 'tmp'
        },

        files: [
          { src: 'js/tinymce/langs', dest: '/content/scripts/tinymce/langs' },
          { src: 'js/tinymce/plugins', dest: '/content/scripts/tinymce/plugins' },
          { src: 'js/tinymce/themes', dest: '/content/scripts/tinymce/themes' },
          { src: 'js/tinymce/skins', dest: '/content/scripts/tinymce/skins' },
          { src: 'js/tinymce/tinymce.js', dest: '/content/scripts/tinymce/tinymce.js' },
          { src: 'js/tinymce/tinymce.min.js', dest: '/content/scripts/tinymce/tinymce.min.js' },
          { src: 'js/tinymce/jquery.tinymce.min.js', dest: '/content/scripts/tinymce/jquery.tinymce.min.js' },
          { src: 'js/tinymce/license.txt', dest: '/content/scripts/tinymce/license.txt' }
        ]
      }
    },

    bundle: {
      minified: {
        options: {
          themesDir: 'js/tinymce/themes',
          pluginsDir: 'js/tinymce/plugins',
          pluginFileName: 'plugin.min.js',
          themeFileName: 'theme.min.js',
          outputPath: 'js/tinymce/tinymce.full.min.js'
        },

        src: [
          'js/tinymce/tinymce.min.js'
        ]
      },

      source: {
        options: {
          themesDir: 'js/tinymce/themes',
          pluginsDir: 'js/tinymce/plugins',
          pluginFileName: 'plugin.js',
          themeFileName: 'theme.js',
          outputPath: 'js/tinymce/tinymce.full.js'
        },

        src: [
          'js/tinymce/tinymce.js'
        ]
      }
    },

    clean: {
      dist: ['js'],
      lib: ['lib'],
      scratch: ['scratch'],
      release: ['tmp']
    },

    'bedrock-manual': {
      core: {
        config: 'tsconfig.json',
        projectdir: '.',
        stopOnFailure: true,
        testfiles: [
          'src/**/test/ts/atomic/**/*Test.ts',
          'src/**/test/ts/browser/**/*Test.ts'
        ],
        customRoutes: 'src/core/test/json/routes.json'
      }
    },

    'bedrock-auto': {
      phantomjs: {
        browser: 'phantomjs',
        config: 'tsconfig.json',
        testfiles: ['src/**/test/ts/**/*Test.ts'],
        stopOnFailure: true,
        overallTimeout: 600000,
        singleTimeout: 300000,
        customRoutes: 'src/core/test/json/routes.json',
        name: 'phantomjs'
      },
      'chrome-headless': {
        browser: 'chrome-headless',
        config: 'tsconfig.json',
        testfiles: ['src/**/test/ts/**/*Test.ts'],
        stopOnFailure: true,
        overallTimeout: 600000,
        singleTimeout: 300000,
        customRoutes: 'src/core/test/json/routes.json',
        name: 'chrome-headless'
      },
      'firefox-headless': {
        browser: 'firefox-headless',
        config: 'tsconfig.json',
        testfiles: ['src/**/test/ts/**/*Test.ts'],
        stopOnFailure: true,
        overallTimeout: 600000,
        singleTimeout: 300000,
        customRoutes: 'src/core/test/json/routes.json',
        name: 'firefox-headless'
      },
      chrome: {
        browser: 'chrome',
        config: 'tsconfig.json',
        testfiles: ['src/**/test/ts/**/*Test.ts'],
        stopOnFailure: true,
        overallTimeout: 600000,
        singleTimeout: 300000,
        customRoutes: 'src/core/test/json/routes.json',
        name: 'chrome'
      },
      firefox: {
        browser: 'firefox',
        config: 'tsconfig.json',
        testfiles: ['src/**/test/ts/**/*Test.ts'],
        stopOnFailure: true,
        overallTimeout: 600000,
        singleTimeout: 300000,
        customRoutes: 'src/core/test/json/routes.json',
        name: 'firefox'
      },
      MicrosoftEdge: {
        browser: 'MicrosoftEdge',
        config: 'tsconfig.json',
        testfiles: ['src/**/test/ts/**/*Test.ts'],
        stopOnFailure: true,
        overallTimeout: 600000,
        singleTimeout: 300000,
        customRoutes: 'src/core/test/json/routes.json',
        name: 'MicrosoftEdge'
      },
      ie: {
        browser: 'ie',
        config: 'tsconfig.json',
        testfiles: ['src/**/test/ts/**/*Test.ts'],
        stopOnFailure: true,
        overallTimeout: 600000,
        singleTimeout: 300000,
        customRoutes: 'src/core/test/json/routes.json',
        name: 'ie'
      }
    },

    watch: {
      skins: {
        files: ['src/skins/lightgray/main/less/**/*'],
        tasks: ['less', 'copy:skins'],
        options: {
          spawn: false
        }
      }
    }
  });

  grunt.registerTask('version', 'Creates a version file', function () {
    grunt.file.write('tmp/version.txt', BUILD_VERSION);
  });

  grunt.registerTask('build-headers', 'Appends build headers to js files', function () {
    var header = '// ' + packageData.version + ' (' + packageData.date + ')\n';
    grunt.file.write('js/tinymce/tinymce.js', header + grunt.file.read('js/tinymce/tinymce.js'));
    grunt.file.write('js/tinymce/tinymce.min.js', header + grunt.file.read('js/tinymce/tinymce.min.js'));
  });

  require('load-grunt-tasks')(grunt);
  grunt.loadTasks('tools/tasks');
  grunt.loadNpmTasks('@ephox/bedrock');
  grunt.loadNpmTasks('@ephox/swag');
  grunt.loadNpmTasks('grunt-tslint');

  grunt.registerTask('prod', [
    'validateVersion',
    'shell:tsc',
    'tslint',
    'globals',
    'rollup',
    'uglify',
    'less',
    'copy',
    'build-headers',
    'clean:release',
    'moxiezip',
    'nugetpack',
    'version'
  ]);

  grunt.registerTask('dev', [
    'shell:tsc',
    'globals',
    'rollup',
    'less',
    'copy'
  ]);

  grunt.registerTask('start', ['webpack-dev-server']);

  grunt.registerTask('default', ['prod']);
  grunt.registerTask('test', ['bedrock-auto:phantomjs']);
};
