import {Graph} from "./graph";
import {GraphElement} from "./graphelement"
import {NodeType} from "./nodetype";
import {SerializedURL} from "../helper/serializedurl";
import {Link} from "./link";
import {GLOBAL_PARAMS} from "../helper/serializableitem";

const NODE_PARAMS = [
    "label",
    "icon",
    "description",
    "references",
    "video",
    "type",
    "banner",
    ...GLOBAL_PARAMS
];
const NODE_SIM_PARAMS = ["index", "x", "y", "vx", "vy", "fx", "fy"]; // Based on https://github.com/d3/d3-force#simulation_nodes

export class Node extends GraphElement {
    public label: string;
    public description: string;
    public type: NodeType;
    public icon: SerializedURL;
    public banner: SerializedURL;
    public video: SerializedURL;
    public references: SerializedURL[];

    constructor(graph: Graph) {
        super(graph);
        this.isNode = true;
    }

    public delete() {
        return this.graph.deleteNode(this);
    }

    public add(graph: Graph = this.graph) {
        this.graph = graph;
        return this.graph.addNode(this);
    }

    /**
     * Calculates a list of all connected links to the current node.
     * @returns Array containing all connected links.
     */
    public links(): Link[] {
        const links: Link[] = [];

        this.graph.links.forEach((link) => {
            if (link.contains(this)) {
                links.push(link);
            }
        });

        return links;
    }

    /**
     * Connects a given node to itself. Only works if they are in the same graph.
     * @param node Other node to connect.
     * @returns The created link, if successful, otherwise undefined.
     */
    public connect(node: Node): Link {
        if (this.graph !== node.graph) {
            return undefined;
        }

        const link = new Link(this.graph);

        link.source = this;
        link.target = node;

        if (link.add()) {
            return link;
        }
    }

    public serialize(): any {
        return this.serializeProperties(NODE_PARAMS);
    }

    public getCleanInstance(): any {
        return {
            ...this.serialize(),
            ...this.serializeProperties(NODE_SIM_PARAMS)
        };
    }
}