const { default: traverse } = require('@babel/traverse');
const t = require('@babel/types');

const isFalsyLiteral = test =>
  (t.isBooleanLiteral(test) && !test.value) ||
  (t.isNumericLiteral(test) && !test.value) ||
  (t.isStringLiteral(test) && !test.value) ||
  t.isNullLiteral(test) ||
  (t.isIdentifier(test) && test.name === 'undefined');

const isTruthyLiteral = test =>
  t.isObjectExpression(test) ||
  t.isArrayExpression(test) ||
  (t.isStringLiteral(test) && test.value) ||
  (t.isBooleanLiteral(test) && test.value) ||
  (t.isNumericLiteral(test) && test.value);

module.exports = function replaceLiteralValuesInTemplate(program) {
  traverse(program, {
    ConditionalExpression(path) {
      let test = path.node.test;
      if (t.isSequenceExpression(test) && test.expressions.length === 1) {
        test = test.expressions[0];
      }

      if (isTruthyLiteral(test)) {
        path.replaceWith(path.node.consequent);
      } else if (isFalsyLiteral(test)) {
        path.replaceWith(path.node.alternate);
      }
    },
    TemplateLiteral(path) {
      if (!path.node.expressions.some(it => t.isStringLiteral(it))) return;

      const quasis = path.node.quasis;
      const expressions = path.node.expressions;

      const newQuasis = [];
      const newExpressions = [];

      let acc = '';
      for (let i = 0; i < quasis.length; i += 1) {
        acc += quasis[i].value.raw;
        if (i in expressions) {
          if (t.isStringLiteral(expressions[i])) {
            acc += expressions[i].value;
          } else {
            newQuasis.push(
              t.templateElement({
                raw: acc
              })
            );
            newExpressions.push(expressions[i]);
            acc = '';
          }
        }
      }
      newQuasis.push(
        t.templateElement({
          raw: acc
        })
      );

      path.replaceWith(t.templateLiteral(newQuasis, newExpressions));
    }
  });
  return program;
};
