'use strict';

const path = require('path');
const sass = require('sass');
const autoprefixer = require('autoprefixer');
const pkg = require('./package.json');

const SWATCHES = [
  'brite',
  'cerulean',
  'cosmo',
  'cyborg',
  'darkly',
  'flatly',
  'journal',
  'litera',
  'lumen',
  'lux',
  'materia',
  'minty',
  'morph',
  'pulse',
  'quartz',
  'sandstone',
  'simplex',
  'sketchy',
  'slate',
  'solar',
  'spacelab',
  'superhero',
  'united',
  'vapor',
  'yeti',
  'zephyr'
];

const BUILD_DIR = 'build/';
const DIST_DIR = 'dist/';
const DOCS_DEST = 'docs/5/';
let buildTheme = '';

module.exports = grunt => {
  grunt.loadNpmTasks('@lodder/grunt-postcss');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-sass');
  grunt.loadNpmTasks('grunt-html');
  grunt.loadNpmTasks('grunt-shell');

  // Force use of Unix newlines
  grunt.util.linefeed = '\n';

  grunt.initConfig({
    clean: {
      build: {
        src: 'dist/*/build.scss'
      }
    },
    concat: {
      dist: {
        src: [],
        dest: ''
      }
    },
    copy: {
      vendor: {
        files: [{
          expand: true,
          cwd: 'node_modules/bootstrap-icons',
          src: ['font/**'],
          dest: 'docs/_vendor/bootstrap-icons/'
        }, {
          expand: true,
          cwd: 'node_modules/prismjs',
          src: ['prism.js', 'themes/prism-okaidia.css'],
          dest: 'docs/_vendor/prismjs/'
        }, {
          expand: true,
          cwd: 'node_modules/bootstrap',
          src: ['dist/**'],
          dest: 'docs/_vendor/bootstrap/'
        }]
      },
      css: {
        files: [{
          expand: true,
          cwd: 'dist',
          src: [
            '**/*.css',
            '**/*.scss',
            '**/*.map'
          ],
          dest: DOCS_DEST
        }]
      }
    },
    sass: {
      options: {
        implementation: sass,
        outputStyle: 'expanded'
      },
      dist: {
        src: [],
        dest: ''
      },
      docs: {
        options: {
          outputStyle: 'compressed',
        },
        src: 'docs/_assets/scss/custom.scss',
        dest: 'docs/_assets/css/custom.min.css'
      }
    },
    postcss: {
      options: {
        processors: [
          autoprefixer({ cascade: false })
        ]
      },
      dist: {
        src: [],
        dest: ''
      },
      docs: {
        src: 'docs/_assets/css/custom.min.css',
        dest: 'docs/_assets/css/custom.min.css'
      }
    },
    cssmin: {
      options: {
        level: {
          1: {
            specialComments: 'all'
          }
        },
        sourceMap: true
      },
      dist: {
        src: [],
        dest: ''
      },
      rtl: {
        src: [],
        dest: ''
      }
    },
    htmllint: {
      options: {
        ignore: [
          /Attribute “autocomplete” is only allowed when the input type is.*/
        ]
      },
      src: [
        'docs/**/*.html',
        '!docs/**/bower_components/**/*.html',
        '!docs/_vendor/**/*.html',
        '!docs/2/**/*.html'
      ]
    },
    connect: {
      options: {
        hostname: 'localhost',
        livereload: 35729,
        port: 3000,
        open: true
      },
      base: {
        options: {
          base: 'docs'
        }
      }
    },
    watch: {
      options: {
        livereload: '<%= connect.options.livereload %>',
        spawn: false
      },
      dev: {
        files: [
          'dist/*/_variables.scss',
          'dist/*/_bootswatch.scss'
        ],
        tasks: ['build', 'shell:csslint']
      }
    },
    shell: {  
      options: {
        stderr: false,
        failOnError: false
      },
      rtlcss: {
        command: function (theme) {
          return `rtlcss dist/${theme}/bootstrap.css dist/${theme}/bootstrap.rtl.css`;
        }
      },
      csslint: {
        command: 'stylelint "dist/**/*.scss"'
      }
    }
  });

  grunt.registerTask('rtlcss', function (theme) {
    grunt.task.run('shell:rtlcss:' + theme);
  });

  grunt.registerTask('build', 'build a regular theme from scss', theme => {
    theme = theme ? theme : buildTheme;

    const themeDir = path.join(DIST_DIR, '/', theme);
    const isValidTheme = grunt.file.exists(path.join(themeDir, '/_variables.scss')) && grunt.file.exists(path.join(themeDir, '/_bootswatch.scss'));

    // cancel the build (without failing) if this directory is not a valid theme
    if (!isValidTheme) {
      grunt.log.writeln(`${theme} theme does not exist!`);
      return;
    }

    const concatSrc = path.join(BUILD_DIR, '/scss/build.scss');
    const concatDest = path.join(themeDir, '/build.scss');
    const cssDest = path.join(themeDir, '/bootstrap.css');
    const cssDestMin = path.join(themeDir, '/bootstrap.min.css');
    const cssDestRtl = path.join(themeDir, '/bootstrap.rtl.css');
    const cssDestRtlMin = path.join(themeDir, '/bootstrap.rtl.min.css');

    const banner = `/*!
 * Bootswatch v${pkg.version} (${pkg.homepage})
 * Theme: ${theme}
 * Copyright 2012-${new Date().getFullYear()} ${pkg.author}
 * Licensed under ${pkg.license}
 * Based on Bootstrap
*/
      `;

    grunt.config.set('concat.options', {banner});
    grunt.config.set('concat.dist', {
      src: concatSrc,
      dest: concatDest
    });
    grunt.config.set('sass.dist', {
      src: concatDest,
      dest: cssDest
    });
    grunt.config.set('postcss.dist', {
      src: cssDest,
      dest: cssDest
    });
    grunt.config.set('copy.css.files.0.cwd', themeDir);
    grunt.config.set('copy.css.files.0.dest', path.join(DOCS_DEST, theme));
    grunt.config.set('cssmin.dist', {
      src: cssDest,
      dest: cssDestMin
    });
    grunt.config.set('cssmin.rtl', {
      src: cssDestRtl,
      dest: cssDestRtlMin
    });

    grunt.task.run([
      'concat',
      'sass:dist',
      'postcss:dist',
      'clean:build',
      'cssmin:dist',
      `rtlcss:${theme}`,
      'cssmin:rtl',
      'copy:css'
    ]);
  });

  grunt.registerTask('swatch', 'build a theme from scss ', theme => {
    // If no theme is passed, build all swatches
    theme = theme ? [theme] : SWATCHES;

    theme.forEach(t => {
      grunt.task.run(`build:${t}`);
    });
  });

  grunt.event.on('watch', (action, filepath) => {
    const theme = path.basename(path.dirname(filepath));

    grunt.log.writeln(`${theme} changed...`);
    buildTheme = theme;
  });

  grunt.registerTask('default', ['connect', 'watch']);
  grunt.registerTask('vendor', 'copy:vendor');
  grunt.registerTask('docs-css', ['sass:docs', 'postcss:docs']);
  grunt.registerTask('docs', ['docs-css', 'vendor']);
  grunt.registerTask('release', ['swatch', 'docs']);
};
