/*
 * Copyright 2015 Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.net.flowobjective.impl.composition;

import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Provides a policy tree to store all flow tables for each device.
 *
 * Note: This class uses in-memory structures and is not yet distributed.
 */
public class FlowObjectiveCompositionTree {

    public FlowObjectiveCompositionManager.PolicyOperator operator;
    public FlowObjectiveCompositionTree leftChild;
    public FlowObjectiveCompositionTree rightChild;
    public short applicationId;
    protected FilterTable filterTable;
    protected ForwardTable forwardTable;
    protected NextTable nextTable;

    protected int priorityMultiplier;
    protected int priorityAddend;

    public FlowObjectiveCompositionTree(short applicationId) {
        this.operator = FlowObjectiveCompositionManager.PolicyOperator.Application;
        this.leftChild = null;
        this.rightChild = null;
        this.applicationId = applicationId;
        this.filterTable = new FilterTable();
        this.forwardTable = new ForwardTable();
        this.nextTable = new NextTable();
        this.priorityMultiplier = 10;
        this.priorityAddend = 10;
    }

    public FlowObjectiveCompositionTree(Character ch) {
        switch (ch) {
            case '+':
                this.operator = FlowObjectiveCompositionManager.PolicyOperator.Parallel;
                break;
            case '>':
                this.operator = FlowObjectiveCompositionManager.PolicyOperator.Sequential;
                break;
            case '/':
                this.operator = FlowObjectiveCompositionManager.PolicyOperator.Override;
                break;
            default:
                this.operator = FlowObjectiveCompositionManager.PolicyOperator.Application;
                break;
        }
        this.leftChild = null;
        this.rightChild = null;
        this.applicationId = (short) -1;
        this.filterTable = new FilterTable();
        this.forwardTable = new ForwardTable();
        this.nextTable = new NextTable();
        this.priorityMultiplier = 10;
        this.priorityAddend = 10;
    }

    protected List<FilteringObjective> updateFilter(FilteringObjective filteringObjective) {
        switch (this.operator) {
            case Parallel:
                return updateFilterParallel(filteringObjective);
            case Sequential:
                return updateFilterSequential(filteringObjective);
            case Override:
                return updateFilterOverride(filteringObjective);
            case Application:
                if (filteringObjective.appId().id() == this.applicationId) {
                    return this.filterTable.updateFilter(filteringObjective);
                } else {
                    return new ArrayList<>();
                }
            default:
                    return new ArrayList<>();
        }
    }

    // Parallel composition: the filter set is the union of the children
    protected List<FilteringObjective> updateFilterParallel(FilteringObjective filteringObjective) {
        List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective);
        List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective);

        List<FilteringObjective> updates = new ArrayList<>();
        updates.addAll(leftUpdates);
        updates.addAll(rightUpdates);

        return this.filterTable.updateFilter(updates);
    }

    // Sequential composition: the filter set is the filter set of the left child
    protected List<FilteringObjective> updateFilterSequential(FilteringObjective filteringObjective) {
        List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective);
        List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective);
        return this.filterTable.updateFilter(leftUpdates);
    }

    // Override composition: the filter set is the filter set of the left child
    protected List<FilteringObjective> updateFilterOverride(FilteringObjective filteringObjective) {
        List<FilteringObjective> leftUpdates = this.leftChild.updateFilter(filteringObjective);
        List<FilteringObjective> rightUpdates = this.rightChild.updateFilter(filteringObjective);
        return this.filterTable.updateFilter(leftUpdates);
    }

    public List<ForwardingObjective> updateForward(ForwardingObjective forwardingObjective) {
        return this.updateForwardNode(forwardingObjective).toForwardingObjectiveList();
    }

    public ForwardUpdateTable updateForwardNode(ForwardingObjective forwardingObjective) {
        switch (this.operator) {
            case Parallel:
            case Sequential:
            case Override:
                return updateForwardComposition(forwardingObjective);
            case Application:
                if (forwardingObjective.appId().id() == this.applicationId) {
                    return this.forwardTable.updateForward(forwardingObjective);
                } else {
                    return (new ForwardUpdateTable());
                }
            default:
                return (new ForwardUpdateTable());
        }
    }

    protected ForwardUpdateTable updateForwardComposition(ForwardingObjective forwardingObjective) {
        ForwardUpdateTable leftUpdates = this.leftChild.updateForwardNode(forwardingObjective);
        ForwardUpdateTable rightUpdates = this.rightChild.updateForwardNode(forwardingObjective);

        List<ForwardingObjective> addUpdates = new ArrayList<>();
        List<ForwardingObjective> removeUpdates = new ArrayList<>();
        // Handle ADD
        if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel
                || this.operator == FlowObjectiveCompositionManager.PolicyOperator.Sequential) {
            for (ForwardingObjective fo1 : leftUpdates.addObjectives) {
                for (ForwardingObjective fo2 : this.rightChild.forwardTable.getForwardingObjectives()) {
                    ForwardingObjective composedFo = null;
                    if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel) {
                        composedFo = FlowObjectiveCompositionUtil.composeParallel(fo1, fo2);
                    } else {
                        composedFo = FlowObjectiveCompositionUtil.composeSequential(fo1, fo2, this.priorityMultiplier);
                    }
                    if (composedFo != null) {
                        addUpdates.add(composedFo);
                        this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo1, composedFo);
                        this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo2, composedFo);
                    }
                }
            }
            Collection<ForwardingObjective> leftTableWithoutAdd = FlowObjectiveCompositionUtil
                    .minusForwardingObjectives(this.leftChild.forwardTable.getForwardingObjectives(),
                            leftUpdates.addObjectives);
            for (ForwardingObjective fo1 : leftTableWithoutAdd) {
                for (ForwardingObjective fo2 : rightUpdates.addObjectives) {
                    ForwardingObjective composedFo = null;
                    if (this.operator == FlowObjectiveCompositionManager.PolicyOperator.Parallel) {
                        composedFo = FlowObjectiveCompositionUtil.composeParallel(fo1, fo2);
                    } else {
                        composedFo = FlowObjectiveCompositionUtil.composeSequential(fo1, fo2, this.priorityMultiplier);
                    }
                    if (composedFo != null) {
                        addUpdates.add(composedFo);
                        this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo1, composedFo);
                        this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo2, composedFo);
                    }
                }
            }
        } else {
            for (ForwardingObjective fo : leftUpdates.addObjectives) {
                ForwardingObjective composedFo = FlowObjectiveCompositionUtil.composeOverride(fo, this.priorityAddend);
                addUpdates.add(composedFo);
                this.leftChild.forwardTable.addGeneratedParentForwardingObjective(fo, composedFo);
            }
            for (ForwardingObjective fo : rightUpdates.addObjectives) {
                ForwardingObjective composedFo = FlowObjectiveCompositionUtil.composeOverride(fo, 0);
                addUpdates.add(composedFo);
                this.rightChild.forwardTable.addGeneratedParentForwardingObjective(fo, composedFo);
            }
        }

        // Handle REMOVE
        for (ForwardingObjective fo : leftUpdates.removeObjectives) {
            List<ForwardingObjective> fos = this.leftChild.forwardTable
                    .getGeneratedParentForwardingObjectiveForRemove(fo);
            removeUpdates.addAll(fos);
        }
        this.leftChild.forwardTable.deleteGeneratedParentForwardingObjective(leftUpdates.removeObjectives);
        for (ForwardingObjective fo : rightUpdates.removeObjectives) {
            List<ForwardingObjective> fos = this.rightChild.forwardTable
                    .getGeneratedParentForwardingObjectiveForRemove(fo);
            removeUpdates.addAll(fos);
        }
        this.rightChild.forwardTable.deleteGeneratedParentForwardingObjective(rightUpdates.removeObjectives);

        ForwardUpdateTable updates = new ForwardUpdateTable();
        updates.addUpdateTable(this.forwardTable.updateForward(addUpdates));
        updates.addUpdateTable(this.forwardTable.updateForward(removeUpdates));
        return updates;
    }

    public List<NextObjective> updateNext(NextObjective nextObjective) {
        switch (this.operator) {
            case Parallel:
            case Sequential:
            case Override:
                return updateNextComposition(nextObjective);
            case Application:
                if (nextObjective.appId().id() == this.applicationId) {
                    return this.nextTable.updateNext(nextObjective);
                } else {
                    return new ArrayList<>();
                }
            default:
                return new ArrayList<>();
        }
    }

    // Next: the union of the children
    protected List<NextObjective> updateNextComposition(NextObjective nextObjective) {
        List<NextObjective> leftUpdates = this.leftChild.updateNext(nextObjective);
        List<NextObjective> rightUpdates = this.rightChild.updateNext(nextObjective);

        List<NextObjective> updates = new ArrayList<>();
        updates.addAll(leftUpdates);
        updates.addAll(rightUpdates);

        return this.nextTable.updateNext(updates);
    }

    @Override
    public String toString() {
        String str = null;
        switch (this.operator) {
            case Parallel:
                str = "(" + this.leftChild + "+" + this.rightChild + ")";
                break;
            case Sequential:
                str = "(" + this.leftChild + ">" + this.rightChild + ")";
                break;
            case Override:
                str = "(" + this.leftChild + "/" + this.rightChild + ")";
                break;
            default:
                str = " " + applicationId + " ";
                break;
        }
        return str;
    }

}
