import { BindingEngine } from '../binding/exported';
import { IBindingContext, IListener } from '../interface/exported';
import { ViewController } from './viewController';
import { Logger } from '../utils/exported';

/**
 * internal subscribe caller of Interpolate controller
 * @internal
 *
 */
const SubscribeInternal = class implements IListener {
    private firstRun = true;
    public name = 'Interpolate';
    public node: Node;

    constructor(node: Node) {
        this.node = node;
    }
    public call(newValue: any, oldValue: any) {
        if (oldValue !== newValue || this.firstRun) {
            this.firstRun = false;
            if ((this.node as any).nodeType === 2) {
                (this.node as Attr).value = newValue;
            } else {
                (this.node as Text).data = newValue;
            }
        }
    }
};



/**
 * Interpolate controller watches the text and updates node
 *
 */
export class InterpolateController {
    private subscribeInternal: IListener;
    private logger: Logger;
    private isAttibuteNode = false;
    public classInstance: any;


    /**
     * Creates instance of InterpolateController
     * @param bindingContext - Binding context to use
     * @param htmlNode - html node of text
     * @param viewController - viewController to use
     * @param _isAttributeValue - is it a attibute value ? debug helper
     */
    constructor(
        private bindingContext: IBindingContext,
        private htmlNode: Node,
        viewController: ViewController,
        _isAttributeValue: boolean) {

        if (!(htmlNode as any).data) {
            this.isAttibuteNode = true;
        }
        this.logger = Logger.getLogger(this.isAttibuteNode ? (htmlNode as any).value.trim() : (htmlNode as any).data.trim(), 'interpolate');

        viewController.addInterpolate(this);
    }



    /**
     * start element life cycle
     *
     */
    public init(): void {
        this.logger.log('init');
        this.subscribeInternal = new SubscribeInternal(this.htmlNode);
        BindingEngine.subscribeClassProperty(
            this.bindingContext,
            this.isAttibuteNode ? (this.htmlNode as any).value : (this.htmlNode as any).data,
            this.subscribeInternal);
    }



    /**
     * attached... dont really do much atm... Todo, should I subscribe here ?
     *
     */
    public attached(): void {
        this.logger.log('attached');
    }



    /**
     * detached, unsubscribes and clear out
     *
     */
    public detached(): void {
        this.logger.log('detached');
        BindingEngine.unSubscribeClassProperty(this.bindingContext, this.subscribeInternal);
        this.subscribeInternal = null;
        this.bindingContext = null;
        this.htmlNode = null;
    }



}
