
import { isString, isEqual, isPlainObject, isUndefined } from 'lodash'
import Expression from './base'

/**
 * @class LiteralExpression
 */
export default class Literal extends Expression {
  
  /**
   * 
   * @param {String} expr
   * @param {Object} values
   * @constructor
   */
  constructor(expr, values = []) {
    super()
    
    this.values = values
    this.expr = expr
    this.before = ''
    this.after = ''
  }

  /**
   * 
   * @param {String|Expression} value
   * @returns {Literal}
   */
  static from(value) {
    return new Literal(value.toString())
  }
  
  /**
   * 
   * @param {String} before
   * @param {String} after
   * @returns {Raw}
   */
  wrap(before = '(', after = ')') {
    this.before = before
    this.after = after
    return this
  }
  
  /**
   * 
   * @param {Compiler} compiler
   * @returns {String}
   */
  compile(compiler) {
    // replace named parameters with 
    if ( isPlainObject(this.values) ) {
      let obj = this.values
      this.values = []

      this.expr = this.expr.replace(/(:\w)/gi, (_, name) => {
        if ( isUndefined(obj[name]) ) return name
        
        this.values.push(obj[name])
        return '?'
      })
    }
    
    var values = this.values.slice()
    var expr = this.expr.replace(/\?\??/g, () => {
      return compiler.parameterize(values.shift())
    })
    
    return compiler.alias(this.before + expr + this.after, this.alias)
  }
  
  /**
   * 
   * @param {Any} expr
   * @returns {Boolean}
   */
  isEqual(expr) {
    if ( isString(expr) )
      return (this.expr === expr || this.alias === expr)

    // TODO compare also the values

    return super.isEqual() || (
      expr instanceof Literal &&
      expr.expr === this.expr &&
      expr.alias === this.alias
    )
  }

  /**
   * 
   * @returns {String}
   */
  toString() {
    return this.expr
  }
  
}
@@ -904,16 +904,37 @@
 rs with 
+the basic placeholder
 %0A    if 
@@ -1059,33 +1059,114 @@
 ce(/
+%5B:@%5D
 (
-:
 %5Cw
++
 )/gi, (
-_, name
+match, attr
 ) =%3E %7B%0A
+        // we return the match string in case the attribute is undefined%0A
     
@@ -1190,20 +1190,20 @@
 ned(obj%5B
-name
+attr
 %5D) ) ret
@@ -1206,20 +1206,21 @@
  return 
-name
+match
 %0A       
@@ -1233,35 +1233,121 @@
     
-this.values.push(obj%5Bname%5D)
+// append the value of the attribute%0A        this.values.push(obj%5Battr%5D)%0A%0A        // return the basic placeholder
 %0A   

Fix bugs