import bemNamingFactory from 'bem-naming';

import {
    prepareClassName,
    paramTypeAssert,
    targetTypeAssert
} from './utils';

const bemNaming = bemNamingFactory({
    // elem: '_',
    // mod: '__'
    // wordPattern: '[a-z0-9]+(?:-[a-z0-9]+)*'
});

export default function(chai) {
    const { Assertion } = chai;
    const { typeOf, isTrue } = chai.assert;

    Assertion.addMethod('block', function(blockName) {
        const className = this._obj;

        typeOf(blockName, 'string');
        typeOf(className, 'string');

        const preparedClassName = prepareClassName(className);

        this.assert(
            preparedClassName.indexOf(blockName) !== -1,
            'expected #{this} to be #{exp} block but got #{act}',
            'expected #{this} to not be #{exp} block but got #{act}',
            blockName,
            className
        );
    });

    Assertion.addMethod('elem', function(bemjson) {
        const className = this._obj;

        typeOf(bemjson, 'object');
        typeOf(className, 'string');

        const preparedClassName = prepareClassName(className);

        isTrue(
            preparedClassName.some(item => bemNaming.isElem(item)),
            `there is no valid element in ${className}`
        );

        this.assert(
            preparedClassName.some(item => {
                return bemNaming.parse(item).elem === bemjson.elem;
            }),
            'expected #{this} to be an elem #{exp} but got #{act}',
            'expected #{this} to not be an elem of #{act} block',
            bemjson,
            className
        );
    });
}

@@ -447,32 +447,55 @@
 e = this._obj;%0A%0A
+        // check input%0A
         typeOf(b
@@ -511,24 +511,24 @@
  'string');%0A
-
         type
@@ -609,32 +609,60 @@
 me(className);%0A%0A
+        // actual assertion%0A
         this.ass
@@ -1006,32 +1006,55 @@
 e = this._obj;%0A%0A
+        // check input%0A
         typeOf(b
@@ -1166,32 +1166,88 @@
 me(className);%0A%0A
+        // check if there is at least one valid element%0A
         isTrue(%0A
@@ -1378,24 +1378,52 @@
         );%0A%0A
+        // actual assertion%0A
         this
@@ -1496,14 +1496,26 @@
     
-return
+const parsedItem =
  bem
@@ -1532,16 +1532,132 @@
 se(item)
+;%0A%0A                return (%0A                    parsedItem.block === bemjson.block &&%0A                    parsedItem
 .elem ==
@@ -1670,16 +1670,34 @@
 son.elem
+%0A                )
 ;%0A      
@@ -1831,18 +1831,34 @@
 f #%7B
-act
+exp
 %7D block
+, but got #%7Bact%7D
 ',%0A 

fix elem assertion not including block into checking