var gulp = require('gulp'),                     // base
    sass     = require('gulp-sass')(require('sass')),   // processes scss files
    concat   = require('gulp-concat'),                  // to merge files
    del      = require('del'),                          // deletes old dist files
    connect  = require('gulp-connect'),                 // creates a local server
    open     = require('gulp-open'),                    // to open a browser istance
    twig     = require('gulp-twig'),
    data     = require('gulp-data'),
    cleanCSS = require('gulp-clean-css'),               // minifies css files
    fs       = require('fs'),
    path     = require('path'),
    gulpif   = require('gulp-if'),  
    bump     = require('gulp-bump'),
    git      = require('gulp-git'),
    filter   = require('gulp-filter'),
    minify     = require('gulp-terser'),
    argv = require('yargs')
        .option('type', {
            alias  : 't',
            choices: ['patch', 'minor', 'major']
        }).argv,

    tag           = require('gulp-tag-version'),
    push          = require('gulp-git-push'),
    inject        = require('gulp-inject-partials'),
    postcss       = require('gulp-postcss'),
    tailwindcss   = require('tailwindcss'),
    autoprefixer  = require('autoprefixer'),
    tailwindForms = require('@tailwindcss/forms'),
    shell         = require('gulp-shell');
    cssnano       = require('cssnano'),
    rename        = require("gulp-rename"),
    webpack       = require('webpack-stream'),
    replace       = require('gulp-replace')

var debug = false;

var version          = '';
var current_version  = '';

var buildFolder  = 'dist/',
    staticFolder = 'static/',
    cssBuildFolder, scriptsBuildFolder, assetsBuildFolder, viewsBuildFolder;

const setFolders = (folder = 'static/') => {
    buildFolder        = folder;
    cssBuildFolder     = buildFolder + 'styles/';
    scriptsBuildFolder = buildFolder + 'scripts/';
    assetsBuildFolder  = buildFolder + 'assets/';
    viewsBuildFolder   = buildFolder + 'views/';
}

setFolders(buildFolder);

// task to delete each file in the dist directory
gulp.task('clean', () => del([cssBuildFolder, scriptsBuildFolder, assetsBuildFolder, buildFolder ]));

// does nothing but set the debug variable
gulp.task('prod', () => { debug = false; return gulp.src('src/'); } );

var getPackageJson = function () {
    return JSON.parse(fs.readFileSync('./package.json', 'utf8'));
};


// task to compile SASS scripts,
// create the css files and reload the page
gulp.task('sass', () =>
    gulp.src('src/styles/**/*.scss')
    .pipe(sass({
        includePaths: ['node_modules'],
        outputStyle : 'compressed',
        precision   : 9
    }).on('error', sass.logError))
    .pipe(cleanCSS({debug: true}, function(details) {
        console.log(details.name + ': ' + details.stats.originalSize);
        console.log(details.name + ': ' + details.stats.minifiedSize);
    }))

    .pipe(gulp.dest(cssBuildFolder))
    .pipe(connect.reload())
);



gulp.task('css', () =>{

    return gulp
        .src('./src/**/*.css')
        .pipe(postcss([
            tailwindcss('./tailwind.config.js'),
            autoprefixer,
            tailwindForms,
            cssnano
        ]))
        .pipe(gulp.dest(cssBuildFolder))
        .pipe(connect.reload());
});



gulp.task('styles:lib', () =>{

    const libs_src = [
        'src/styles/lib/*.css'
    ];

    return gulp.src(libs_src)
    .pipe(concat('main-libs.css'))
    .pipe(gulp.dest(cssBuildFolder+'/lib'))
    .pipe(connect.reload());
});

gulp.task('styles:node_lib', () =>{

    const libs_src = [ 'node_modules/swiper/swiper-bundle.min.css',
                       'node_modules/lite-youtube-embed/src/lite-yt-embed.css',
                       'node_modules/@fancyapps/ui/dist/fancybox/fancybox.css'
                     ];

    return gulp.src(libs_src)
    //.pipe(concat('main-libs.css'))
    //.pipe(rename( path => { path.basename += current_version;  path.extname = '.css' }  ))
    .pipe(gulp.dest(cssBuildFolder+'/lib'))
    .pipe(connect.reload());
});

gulp.task('scripts:lib', () =>{

    const libs_src = [
        'src/scripts/lib/*.js'
    ];

    return gulp.src(libs_src)
    .pipe(concat('main-libs.js'))
    .pipe(gulp.dest(scriptsBuildFolder+'/lib'))
    .pipe(connect.reload());
});

gulp.task('scripts:node_lib', function() {

    const libs_src = [  'node_modules/alpinejs/dist/cdn.min.js',
                        'node_modules/swiper/swiper-bundle.min.js',
                        'node_modules/lite-youtube-embed/src/lite-yt-embed.js',
                        'node_modules/@fancyapps/ui/dist/fancybox/fancybox.umd.js'
                     ];

    return gulp.src( libs_src )        
        //.pipe( rename( path => { path.basename += current_version;  path.extname = '.js' } ) )
        .pipe( gulp.dest( `${scriptsBuildFolder}/lib` ) )
        .pipe( connect.reload() );
});


gulp.task( 'main_modules',  function() {
    return gulp.src(['src/scripts/modules/*.js'])
        .pipe( gulpif( !debug, minify( minifyOptions ) ) )
        .pipe(gulp.dest(`${scriptsBuildFolder}/modules/`));
});

gulp.task( 'main_file',  function() {
    return gulp.src('src/scripts/main.js')
        .pipe( gulpif( !debug, webpack( { mode : 'production' } ) ) ) 
        /// solo per test poi deve valere la riga sopra
        //.pipe( webpack( { mode : 'production' } ) )
        //.pipe( rename( path => { path.basename += current_version;  path.extname = '.js' } ) )
        .pipe( gulp.dest(scriptsBuildFolder) );
});


gulp.task('ajax', function() {
    return gulp.src('src/ajax/**/*')
        .pipe(gulp.dest(buildFolder+'ajax/'));
});


gulp.task('html', function() {
    return gulp.src('src/**/*.html')
        .pipe(gulp.dest(buildFolder))
        .pipe(connect.reload());
});

gulp.task('assets', function() {
    return gulp.src(['src/assets/**/*'])
        .pipe(gulp.dest(assetsBuildFolder));
});


// Compile Twig templates to HTML
gulp.task('templates', function() {

    console.log('task-templates buildfolder : ', buildFolder );

    return gulp.src('src/**/*.twig') // run the Twig template parser on all .html files in the "src" directory
        //.pipe(twig('twig_data.json'))

        // each twig templates has a json that contains
        // its own sample data
        .pipe(data(function (file) {

            let hasBackslashes = (file.path.indexOf('\\') != -1);
            let filepath = file.path.replace(/\\/g,"/").split('/');
            let filename = filepath[ filepath.length-1 ];

            filepath[ filepath.length - 1 ] = 'data/'+filename+'.json';
            jsonpath = filepath.join('/');
            if (hasBackslashes) jsonpath =  jsonpath.replace(/\//g,"\\");

            let data = {};
            if (fs.existsSync(jsonpath))
                data = JSON.parse(fs.readFileSync(jsonpath));
            return data;
        }))
        .pipe( twig({ base: __dirname + '/src/' }) )

        .pipe( gulp.dest(buildFolder) ) // output the rendered HTML files to the "dist" directory
        .pipe(connect.reload());

});

// Task per aggiornare il path del CSS in header.twig
gulp.task('replace-css', function() {
    return gulp.src('static/views/templates/header.twig') // Sostituisci con il percorso corretto al file
        .pipe(replace(
            /\/styles\/styles\/style\.css\?ver=\{\{ version \}\}/, 
            '/system_/vendor/blazemedia/hdb_frontend/static/styles/styles/style.css?ver={{version}}'
        ))
        .pipe(gulp.dest('static/views/templates')); // Salva il file aggiornato
});

// Task per aggiornare il path del CSS in header.twig
gulp.task('replace-js', function() {
    return gulp.src('static/views/templates/footer.twig') // Sostituisci con il percorso corretto al file
        .pipe(replace(
            /\/scripts\/lib\/cdn\.min\.js\?v=\{\{version\}\}/, 
            '/system_/vendor/blazemedia/hdb_frontend/static/scripts/lib/cdn.min.js?v={{version}}'
        ))
        .pipe(gulp.dest('static/views/templates')); // Salva il file aggiornato
});



// Task per sostituire {{assets_dir}} in tutti i file .twig sotto la directory src
gulp.task('replace-assets', function() {
    return gulp.src('static/views/**/*.twig', { base: 'static/views' }) // Mantiene la struttura di src
        .pipe(replace(
            /\{\{assets_dir\}\}/g, 
            '/system_/vendor/blazemedia/hdb_frontend/static/assets' // Nuovo percorso
        ))
        .pipe(gulp.dest('static/views')); // Salva i file mantenendo la struttura sotto /static
});

// Export Twig templates
gulp.task('views', function() {

    console.log('views into : ', viewsBuildFolder );

    return gulp.src('src/**/*.twig') // run the Twig template parser on all .html files in the "src" directory

        // copy rendered twig files to the "dist" directory
        .pipe( gulp.dest(viewsBuildFolder) )
        .pipe(connect.reload());

});

let script_tasks = debug ? ['main_modules', 'main_file'] : 'main_file';

gulp.task('scripts', gulp.parallel( script_tasks ) );

gulp.task('watch', function () {
    gulp.watch('src/styles/**/*.scss', gulp.series('sass', 'templates'));
    gulp.watch('src/scripts/**/*.js', gulp.series('scripts','scripts:lib'));
    gulp.watch('src/assets/**/*', gulp.series('assets'));
    gulp.watch('src/**/*.twig', gulp.series('templates', 'css'));
    gulp.watch('src/**/*.css', gulp.series('templates', 'css'));
    gulp.watch('src/data/**/*.json', gulp.series('templates', 'css'));
});




gulp.task('connect', function() {
    connect.server({
        root: buildFolder,
        host: '0.0.0.0',
        port: 8887,
        livereload: true
    });
});

gulp.task('browser', function(){
    gulp.src(buildFolder + 'index.html')
        .pipe(open({uri: 'http://localhost:8887'}));
});


var getPackageJson = function () {
    return JSON.parse( fs.readFileSync('./package.json', 'utf8'));
};


/**
 * Imposta le variabili di versione attuali leggendole dal package-json
 */
 gulp.task('version', () => {

    setFolders( staticFolder );

    const pkg = getPackageJson();
    version         = pkg.version;
    current_version = pkg.version.replace(/\./g,'_');  // serve trasformare i punti in underscore per l'injection;

    return gulp.src('src/');
} );

const minifyOptions =  {
    // REFS --->  https://www.digitalocean.com/community/tools/minify            
    compress : {
        dead_code     : true,
        drop_console  : true,
        drop_debugger : true,
        keep_fargs    : true
    },
    mangle: false,
    module: false,
    sourceMap: false,
    output: {
        comments: false
    }
};




/**
 * Modifica la versione del progetto
 * prende l'opzione -t per stabilire il tipo di avanzamento
 * 'patch' ( default ), 'minor', 'major'
 */
gulp.task( 'bump', function () {

    return gulp.src('package.json')
           .pipe( bump( { type: argv.type || 'patch' }) )
           .pipe( gulp.dest('./') );

});




/**
 * aggiunge i nuovi file elaborati con git add
 * e poi fa il commit utilizzando la nuova versione
 */
gulp.task( 'commit', function() {

    return gulp.src( [ buildFolder + '*', 'package.json' ] )
        .pipe( git.add({args: '-f'}) ) // Run git add
        .pipe( git.commit( `Bump to version ${ version }` ))
        .pipe( filter('package.json')) // filtra il solo package.json
        .pipe( tag() )                 // così tag prende solo la versione del package.json
        .pipe( push({
            repository: 'origin',
            refspec   : 'HEAD'
        }) );
}.bind( this ) );




gulp.task('common-chain',
    gulp.series('clean', 'assets', 'sass', 'views', 'css',
        gulp.parallel('scripts', 'scripts:lib', 'scripts:node_lib', 'styles:node_lib', 'styles:lib', 'html', 'css'),
    )
);

gulp.task('default',
    gulp.series( 'common-chain', 'templates', gulp.parallel('connect','watch','browser') )
);

gulp.task('serve',
    gulp.series( 'common-chain', 'templates', gulp.parallel('connect','watch') )
);

gulp.task('build', gulp.series('common-chain' ));

// updates version and saves file in the /static folder
gulp.task('build-bump',  gulp.series('bump', 'version', 'common-chain', 'commit'));

// updates version and saves file in the /static folder, removes console logs and minifies CSS and JS
gulp.task('build-prod',  gulp.series('bump', 'version', 'prod', 'common-chain', 'templates', 'commit'));

gulp.task('build-replace',  gulp.series('replace-css', 'replace-js', 'replace-assets', 'bump', 'commit'));
