#include "FilteringTransition.hpp"
#include "ParallelTransition.hpp"
#include "AtomicSequentialTransition.hpp"
#include "BlendTransition.hpp"
#include "MoveTransition.hpp"
#include "ScaleTransition.hpp"
#include "RotateTransition.hpp"
#include "Delay.hpp"
#include "Bar.hpp"
#include "PieSector.hpp"
#include "StackedBar.hpp"

FilteringTransition::FilteringTransition(Chart* pInitialChart) {
  iType = FILTERING_TRANSITION;
  this->pInitialChart = pInitialChart;

  bool bDescending = pInitialChart->GetDataSet()->GetSortingOrder();
  bool bShowAll = pInitialChart->GetDataSet()->GetFiltering();
  std::vector<DataElement*> vAllDataElements = pInitialChart->GetDataElements();
  
  switch (this->pInitialChart->GetType()) {
    case BAR_CHART: {
      pResultChart = new BarChart(pInitialChart->GetDataSet());
      
      std::vector<DataElement*> vVisibleDataElements; //remain or are made visible
      std::vector<DataElement*> vInvisibleDataElements; //are faded out

      if (bDescending) {
        vVisibleDataElements.insert(vVisibleDataElements.begin(),
          vAllDataElements.begin(), vAllDataElements.begin() + FILTER_SIZE);
        vInvisibleDataElements.insert(vInvisibleDataElements.begin(),
          vAllDataElements.begin() + FILTER_SIZE, vAllDataElements.end());
      }
      else {
        vVisibleDataElements.insert(vVisibleDataElements.begin(),
          vAllDataElements.end() - FILTER_SIZE, vAllDataElements.end());
        vInvisibleDataElements.insert(vInvisibleDataElements.begin(),
          vAllDataElements.begin(), vAllDataElements.end() - FILTER_SIZE);
      }

      //sequential transition to order moving/scaling and fading
      AtomicSequentialTransition* pAtomicSequentialTransition = new AtomicSequentialTransition();
      AddTransition(pAtomicSequentialTransition);

      //two parallel transitions for moving/scaling and fading
      ParallelTransition* pFirstParallelTransition = new ParallelTransition();
      pAtomicSequentialTransition->AddTransition(pFirstParallelTransition);

      ParallelTransition* pSecondParallelTransition = new ParallelTransition();
      pAtomicSequentialTransition->AddTransition(pSecondParallelTransition);

      if (bShowAll) {
        //scale and move the elements
        for (unsigned int i = 0; i < vVisibleDataElements.size(); i++) {
          Bar* pDataElement = (Bar*) vVisibleDataElements.at(i);
          Bar* pResultDataElement = (Bar*) pResultChart->GetConnectedDataElement(pDataElement->GetDataEntry());

          ParallelTransition* pScaleAndMoveTransition = new ParallelTransition();
          pFirstParallelTransition->AddTransition(pScaleAndMoveTransition);

          //scale the element
          pScaleAndMoveTransition->AddTransition(new ScaleTransition(pDataElement,
            pResultDataElement->GetWidth() - pDataElement->GetWidth(), 0.0f, FILTERING_SCALE_STEPS));

          //move the element
          pScaleAndMoveTransition->AddTransition(new MoveTransition(pDataElement,
            pResultDataElement->GetLeft() - pDataElement->GetLeft(),
            pResultDataElement->GetTop() - pDataElement->GetTop(),
            pResultDataElement->GetBottom() - pDataElement->GetBottom(), false));
        }

        //get the missing data elements from pResultChart
        std::vector<DataElement*> vMissingDataElements = CloneMissingDataElements();

        //add the missing data elements to the initial chart and fade them in
        for (unsigned int i = 0; i < vMissingDataElements.size(); i++) {
          DataElement* pDataElement = vMissingDataElements.at(i);
          pInitialChart->AddDataElement(pDataElement);

          //the missing data elements should be invisible at the beginning of the transition
          pDataElement->ChangeAlpha(-1.0f);

          pSecondParallelTransition->AddTransition(new BlendTransition(pDataElement, 1.0f));
        }
      }
      else {
        //fade the data elements out
        for (unsigned int i = 0; i < vInvisibleDataElements.size(); i++) {
          DataElement* pDataElement = vInvisibleDataElements.at(i);
          
          pFirstParallelTransition->AddTransition(new BlendTransition(pDataElement, 0.0f));
        }

        //scale and move the elements
        for (unsigned int i = 0; i < vVisibleDataElements.size(); i++) {
          Bar* pDataElement = (Bar*) vVisibleDataElements.at(i);
          Bar* pResultDataElement = (Bar*) pResultChart->GetConnectedDataElement(pDataElement->GetDataEntry());

          ParallelTransition* pScaleAndMoveTransition = new ParallelTransition();
          pSecondParallelTransition->AddTransition(pScaleAndMoveTransition);

          //scale the element
          pScaleAndMoveTransition->AddTransition(new ScaleTransition(pDataElement,
            pResultDataElement->GetWidth() - pDataElement->GetWidth(), 0.0f, FILTERING_SCALE_STEPS));

          //move the element
          pScaleAndMoveTransition->AddTransition(new MoveTransition(pDataElement,
            pResultDataElement->GetLeft() - pDataElement->GetLeft(),
            pResultDataElement->GetTop() - pDataElement->GetTop(),
            pResultDataElement->GetBottom() - pDataElement->GetBottom(), false));
        }
      }

      break;
    }
    case GROUPED_BAR_CHART: {
      pResultChart = new GroupedBarChart(pInitialChart->GetDataSet());

      GroupedBarChart* pCastedInitialChart = (GroupedBarChart*) pInitialChart;
      
      std::vector<DataElement*> vAllBars = pCastedInitialChart->GetAllBars();
      std::vector<DataElement*> vVisibleDataElements; //remain or are made visible
      std::vector<DataElement*> vInvisibleDataElements; //are faded out

      if (bDescending) {
        vVisibleDataElements.insert(vVisibleDataElements.begin(),
          vAllBars.begin(), vAllBars.begin() + FILTER_SIZE);
        vInvisibleDataElements.insert(vInvisibleDataElements.begin(),
          vAllBars.begin() + FILTER_SIZE, vAllBars.end());
      }
      else {
        vVisibleDataElements.insert(vVisibleDataElements.begin(),
          vAllBars.end() - FILTER_SIZE, vAllBars.end());
        vInvisibleDataElements.insert(vInvisibleDataElements.begin(),
          vAllBars.begin(), vAllBars.end() - FILTER_SIZE);
      }

      //sequential transition to order moving/scaling and fading
      AtomicSequentialTransition* pAtomicSequentialTransition = new AtomicSequentialTransition();
      AddTransition(pAtomicSequentialTransition);

      //two parallel transitions for moving/scaling and fading
      ParallelTransition* pFirstParallelTransition = new ParallelTransition();
      pAtomicSequentialTransition->AddTransition(pFirstParallelTransition);

      ParallelTransition* pSecondParallelTransition = new ParallelTransition();
      pAtomicSequentialTransition->AddTransition(pSecondParallelTransition);

      if (bShowAll) {
        //scale and move the elements
        for (unsigned int i = 0; i < vVisibleDataElements.size(); i++) {
          Bar* pDataElement = (Bar*) vVisibleDataElements.at(i);
          Bar* pResultDataElement = (Bar*) ((GroupedBarChart*) pResultChart)->GetConnectedBar(pDataElement->GetDataEntry());

          ParallelTransition* pScaleAndMoveTransition = new ParallelTransition();
          pFirstParallelTransition->AddTransition(pScaleAndMoveTransition);

          //scale the element
          pScaleAndMoveTransition->AddTransition(new ScaleTransition(pDataElement,
            pResultDataElement->GetWidth() - pDataElement->GetWidth(), 0.0f, FILTERING_SCALE_STEPS));

          //move the element
          pScaleAndMoveTransition->AddTransition(new MoveTransition(pDataElement,
            pResultDataElement->GetLeft() - pDataElement->GetLeft(),
            pResultDataElement->GetTop() - pDataElement->GetTop(),
            pResultDataElement->GetBottom() - pDataElement->GetBottom(), false));
        }

        //get the missing data elements from pResultChart
        std::vector<DataElement*> vMissingDataElements = CloneMissingDataElements();

        //add the missing data elements to the initial chart and fade them in
        for (unsigned int i = 0; i < vMissingDataElements.size(); i++) {
          DataElement* pDataElement = vMissingDataElements.at(i);
          pInitialChart->AddDataElement(pDataElement);

          //the missing data elements should be invisible at the beginning of the transition
          pDataElement->ChangeAlpha(-1.0f);

          pSecondParallelTransition->AddTransition(new BlendTransition(pDataElement, 1.0f));
        }
      }
      else {
        //fade the data elements out
        for (unsigned int i = 0; i < vInvisibleDataElements.size(); i++) {
          DataElement* pDataElement = vInvisibleDataElements.at(i);

          pFirstParallelTransition->AddTransition(new BlendTransition(pDataElement, 0.0f));
        }

        //scale and move the elements
        for (unsigned int i = 0; i < vVisibleDataElements.size(); i++) {
          Bar* pDataElement = (Bar*) vVisibleDataElements.at(i);
          Bar* pResultDataElement = (Bar*) ((GroupedBarChart*) pResultChart)->GetConnectedBar(pDataElement->GetDataEntry());

          if (pResultDataElement != NULL) {
            ParallelTransition* pScaleAndMoveTransition = new ParallelTransition();
            pSecondParallelTransition->AddTransition(pScaleAndMoveTransition);

            //scale the element
            pScaleAndMoveTransition->AddTransition(new ScaleTransition(pDataElement,
              pResultDataElement->GetWidth() - pDataElement->GetWidth(), 0.0f, FILTERING_SCALE_STEPS));

            //move the element
            pScaleAndMoveTransition->AddTransition(new MoveTransition(pDataElement,
              pResultDataElement->GetLeft() - pDataElement->GetLeft(),
              pResultDataElement->GetTop() - pDataElement->GetTop(),
              pResultDataElement->GetBottom() - pDataElement->GetBottom(), false));
          }
        }
      }

      break;
    }
    case STACKED_BAR_CHART: {
      pResultChart = new StackedBarChart(pInitialChart->GetDataSet());

      StackedBarChart* pCastedInitialChart = (StackedBarChart*) pInitialChart;

      std::vector<DataElement*> vInitialDataElements = pInitialChart->GetDataElements();
      std::vector<DataElement*> vAllBars = pCastedInitialChart->GetAllBars();
      std::vector<DataElement*> vVisibleDataElements; //remain or are made visible
      std::vector<DataElement*> vInvisibleDataElements; //are faded out

      if (bDescending) {
        vVisibleDataElements.insert(vVisibleDataElements.begin(),
          vAllBars.begin(), vAllBars.begin() + FILTER_SIZE);
        vInvisibleDataElements.insert(vInvisibleDataElements.begin(),
          vAllBars.begin() + FILTER_SIZE, vAllBars.end());
      }
      else {
        vVisibleDataElements.insert(vVisibleDataElements.begin(),
          vAllBars.end() - FILTER_SIZE, vAllBars.end());
        vInvisibleDataElements.insert(vInvisibleDataElements.begin(),
          vAllBars.begin(), vAllBars.end() - FILTER_SIZE);
      }

      //sequential transition to order moving/scaling and fading
      AtomicSequentialTransition* pAtomicSequentialTransition = new AtomicSequentialTransition();
      AddTransition(pAtomicSequentialTransition);

      //two parallel transitions for moving/scaling and fading
      ParallelTransition* pFirstParallelTransition = new ParallelTransition();
      pAtomicSequentialTransition->AddTransition(pFirstParallelTransition);

      ParallelTransition* pSecondParallelTransition = new ParallelTransition();
      pAtomicSequentialTransition->AddTransition(pSecondParallelTransition);

      if (bShowAll) {
        //scale and move the elements
        for (unsigned int i = 0; i < vVisibleDataElements.size(); i++) {
          Bar* pDataElement = (Bar*) vVisibleDataElements.at(i);
          Bar* pResultDataElement = (Bar*) ((StackedBarChart*) pResultChart)->GetConnectedBar(pDataElement->GetDataEntry());

          ParallelTransition* pScaleAndMoveTransition = new ParallelTransition();
          pFirstParallelTransition->AddTransition(pScaleAndMoveTransition);

          //scale the element
          pScaleAndMoveTransition->AddTransition(new ScaleTransition(pDataElement,
            pResultDataElement->GetWidth() - pDataElement->GetWidth(), 0.0f, FILTERING_SCALE_STEPS));

          //move the element
          pScaleAndMoveTransition->AddTransition(new MoveTransition(pDataElement,
            pResultDataElement->GetLeft() - pDataElement->GetLeft(),
            pResultDataElement->GetTop() - pDataElement->GetTop(),
            pResultDataElement->GetBottom() - pDataElement->GetBottom(), false));
        }

        //get the missing data elements from pResultChart
        std::vector<DataElement*> vMissingDataElements = CloneMissingDataElements();

        //add the missing data elements to the initial chart and fade them in
        for (unsigned int i = 0; i < vMissingDataElements.size(); i++) {
          DataElement* pDataElement = vMissingDataElements.at(i);
          pInitialChart->AddDataElement(pDataElement);

          //the missing data elements should be invisible at the beginning of the transition
          pDataElement->ChangeAlpha(-1.0f);

          pSecondParallelTransition->AddTransition(new BlendTransition(pDataElement, 1.0f));
        }
      }
      else {
        //fade the data elements out
        for (unsigned int i = 0; i < vInvisibleDataElements.size(); i++) {
          DataElement* pDataElement = vInvisibleDataElements.at(i);

          pFirstParallelTransition->AddTransition(new BlendTransition(pDataElement, 0.0f));
        }

        //scale and move the elements
        for (unsigned int i = 0; i < vVisibleDataElements.size(); i++) {
          Bar* pDataElement = (Bar*) vVisibleDataElements.at(i);
          Bar* pResultDataElement = (Bar*) ((StackedBarChart*) pResultChart)->GetConnectedBar(pDataElement->GetDataEntry());

          if (pResultDataElement != NULL) {
            ParallelTransition* pScaleAndMoveTransition = new ParallelTransition();
            pSecondParallelTransition->AddTransition(pScaleAndMoveTransition);

            //scale the element
            pScaleAndMoveTransition->AddTransition(new ScaleTransition(pDataElement,
              pResultDataElement->GetWidth() - pDataElement->GetWidth(), 0.0f, FILTERING_SCALE_STEPS));

            //move the element
            pScaleAndMoveTransition->AddTransition(new MoveTransition(pDataElement,
              pResultDataElement->GetLeft() - pDataElement->GetLeft(),
              pResultDataElement->GetTop() - pDataElement->GetTop(),
              pResultDataElement->GetBottom() - pDataElement->GetBottom(), false));
          }
        }
      }

      break;
    }
    case PIE_CHART: {
      pResultChart = new PieChart(pInitialChart->GetDataSet());

      PieChart* pCastedInitialChart = (PieChart*) pInitialChart;
      PieChart* pCastedResultChart = (PieChart*) pResultChart;

      std::vector<PieSlice*> vAllSlices = pCastedInitialChart->GetAllSlices();
      std::vector<DataElement*> vInitialDataElements = pInitialChart->GetDataElements();
      std::vector<DataElement*> vResultDataElements = pResultChart->GetDataElements();
      std::vector<PieSlice*> vVisibleDataElements; //remain or are made visible
      std::vector<PieSlice*> vInvisibleDataElements; //are faded out

      if (bDescending) {
        vVisibleDataElements.insert(vVisibleDataElements.begin(),
          vAllSlices.begin(), vAllSlices.begin() + FILTER_SIZE);
        vInvisibleDataElements.insert(vInvisibleDataElements.begin(),
          vAllSlices.begin() + FILTER_SIZE, vAllSlices.end());
      }
      else {
        vVisibleDataElements.insert(vVisibleDataElements.begin(),
          vAllSlices.end() - FILTER_SIZE, vAllSlices.end());
        vInvisibleDataElements.insert(vInvisibleDataElements.begin(),
          vAllSlices.begin(), vAllSlices.end() - FILTER_SIZE);
      }

      //sequential transition to order rotating/scaling and fading
      AtomicSequentialTransition* pAtomicSequentialTransition = new AtomicSequentialTransition();
      AddTransition(pAtomicSequentialTransition);

      //two parallel transitions for rotating/scaling and fading
      ParallelTransition* pFirstParallelTransition = new ParallelTransition();
      ParallelTransition* pSecondParallelTransition = new ParallelTransition();

      if (bShowAll) {
        //fade out the labels
        ParallelTransition* pFadeLabelsOutTransition = new ParallelTransition();
        pAtomicSequentialTransition->AddTransition(pFadeLabelsOutTransition);

        for (unsigned int i = 0; i < vInitialDataElements.size(); i++) {
          pFadeLabelsOutTransition->AddTransition(new BlendTransition(((PieSector*) vInitialDataElements.at(i))->GetLabel(), -1.0f));
        }
        
        pAtomicSequentialTransition->AddTransition(pFirstParallelTransition);
        pAtomicSequentialTransition->AddTransition(pSecondParallelTransition);

        //scale and rotate the elements
        for (unsigned int i = 0; i < vVisibleDataElements.size(); i++) {
          PieSlice* pDataElement = vVisibleDataElements.at(i);
          PieSlice* pResultDataElement = (PieSlice*) pCastedResultChart->GetConnectedSlice(pDataElement->GetDataEntry());

          ParallelTransition* pScaleAndMoveTransition = new ParallelTransition();
          pFirstParallelTransition->AddTransition(pScaleAndMoveTransition);

          //scale the element
          pScaleAndMoveTransition->AddTransition(new ScaleTransition(pDataElement,
            pResultDataElement->GetWidth() - pDataElement->GetWidth(), 0.0f, FILTERING_SCALE_STEPS));

          //rotate the element
          pScaleAndMoveTransition->AddTransition(new RotateTransition(pDataElement,
            pResultDataElement->GetBeginValue() - pDataElement->GetBeginValue(), FILTERING_SCALE_STEPS));
        }

        //get the missing data elements from pResultChart
        std::vector<DataElement*> vMissingDataElements = CloneMissingDataElements();

        //add the missing data elements to the initial chart and fade them in
        for (unsigned int i = 0; i < vMissingDataElements.size(); i++) {
          PieSlice* pDataElement = (PieSlice*) vMissingDataElements.at(i);
          pInitialChart->AddDataElement(pDataElement);

          //the missing data elements should be invisible at the beginning of the transition
          pDataElement->ChangeAlpha(-1.0f);

          pSecondParallelTransition->AddTransition(new BlendTransition(pDataElement, 1.0f));
        }

        //fade in the new labels
        for (unsigned int i = 0; i < vResultDataElements.size(); i++) {
          Label* pResultLabel = ((PieSector*) vResultDataElements.at(i))->GetLabel();
          Label* pNewLabel = new Label(pResultLabel->GetText(), pResultLabel->GetStyle(),
            pResultLabel->GetLeft(), pResultLabel->GetTop(), pResultLabel->GetOrientation(),
            pResultLabel->GetAlignment());
          pNewLabel->ChangeAlpha(-1.0f);

          pInitialChart->AddLabel(pNewLabel);

          pSecondParallelTransition->AddTransition(new BlendTransition(pNewLabel, 1.0f));
        }
      }
      else {
        pAtomicSequentialTransition->AddTransition(pFirstParallelTransition);
        pAtomicSequentialTransition->AddTransition(pSecondParallelTransition);

        for (unsigned int i = 0; i < vInitialDataElements.size(); i++) {
          pFirstParallelTransition->AddTransition(new BlendTransition(((PieSector*) vInitialDataElements.at(i))->GetLabel(), -1.0f));
        }

        //fade the data elements out
        for (unsigned int i = 0; i < vInvisibleDataElements.size(); i++) {
          DataElement* pDataElement = vInvisibleDataElements.at(i);

          pFirstParallelTransition->AddTransition(new BlendTransition(pDataElement, 0.0f));
        }

        for (unsigned int i = 0; i < vVisibleDataElements.size(); i++) {
          PieSlice* pDataElement = vVisibleDataElements.at(i);
          PieSlice* pResultDataElement = (PieSlice*) pCastedResultChart->GetConnectedSlice(pDataElement->GetDataEntry());

          ParallelTransition* pScaleAndMoveTransition = new ParallelTransition();
          pSecondParallelTransition->AddTransition(pScaleAndMoveTransition);

          //scale the element
          pScaleAndMoveTransition->AddTransition(new ScaleTransition(pDataElement,
            pResultDataElement->GetWidth() - pDataElement->GetWidth(), 0.0f, FILTERING_SCALE_STEPS));

          //rotate the element
          pScaleAndMoveTransition->AddTransition(new RotateTransition(pDataElement,
            pResultDataElement->GetBeginValue() - pDataElement->GetBeginValue(), FILTERING_SCALE_STEPS));
        }

        //fade in the new labels
        ParallelTransition* pFadeLabelsInTransition = new ParallelTransition();
        pAtomicSequentialTransition->AddTransition(pFadeLabelsInTransition);

        for (unsigned int i = 0; i < vResultDataElements.size(); i++) {
          Label* pResultLabel = ((PieSector*) vResultDataElements.at(i))->GetLabel();
          Label* pNewLabel = new Label(pResultLabel->GetText(), pResultLabel->GetStyle(),
            pResultLabel->GetLeft(), pResultLabel->GetTop(), pResultLabel->GetOrientation(),
            pResultLabel->GetAlignment());
          pNewLabel->ChangeAlpha(-1.0f);

          pInitialChart->AddLabel(pNewLabel);

          pFadeLabelsInTransition->AddTransition(new BlendTransition(pNewLabel, 1.0f));
        }
      }

      break;
    }
    default: {
      //this should not be possible, fall back to bar chart
      pResultChart = new BarChart(this->pInitialChart->GetDataSet());
    }
  }
}

FilteringTransition::~FilteringTransition() {
  while (vChildren.size() > 0) {
    std::vector<Transition*>::iterator it = vChildren.begin();

    if (it != vChildren.end()) {
      delete *it;
      vChildren.erase(it);
    }
  }

  while (vToBeDeleted.size() > 0) {
    std::vector<AlterableObject*>::iterator it = vToBeDeleted.begin();

    if (it != vToBeDeleted.end()) {
      delete *it;
      vToBeDeleted.erase(it);
    }
  }
}

void FilteringTransition::Update() {
  if ((vChildren.size() > 0) && (vChildren.at(0)->Complete())) {
    delete *vChildren.begin();
    vChildren.erase(vChildren.begin());
  }

  if (vChildren.size() > 0) {
    vChildren.at(0)->Update();
  }
}

void FilteringTransition::Draw(QPainter* pPainter) {
  pInitialChart->Draw(pPainter);
  pInitialChart->DrawLabels(pPainter);
}

bool FilteringTransition::Complete() {
  for (unsigned int i = 0; i < vChildren.size(); i++) {
    if (!vChildren.at(i)->Complete()) {
      return false;
    }
  }

  return true;
}

std::vector<DataElement*> FilteringTransition::CloneMissingDataElements() {
  std::vector<DataElement*> vMissingDataElements;
  std::vector<DataElement*> vResultDataElements = pResultChart->GetDataElements();

  if ((pInitialChart != NULL) && (pResultChart != NULL) && (vResultDataElements.size() > 0)) {
    switch (vResultDataElements.at(0)->GetType()) {
      case BAR: {
        for (unsigned int i = 0; i < vResultDataElements.size(); i++) {
          DataElement* pDataElement = vResultDataElements.at(i);

          if (pInitialChart->GetConnectedDataElement(vResultDataElements.at(i)->GetDataEntry()) == NULL) {
            Bar* pBar = (Bar*) pDataElement;
            vMissingDataElements.push_back(new Bar(pBar->GetDataEntry(),
              pBar->GetLeft(), pBar->GetTop(), pBar->GetBottom(), pBar->GetWidth()));
          }
        }

        break;
      }
      case GROUPED_BAR: {
        std::vector<DataElement*> vResultBars = ((GroupedBarChart*) pResultChart)->GetAllBars();

        for (unsigned int i = 0; i < vResultBars.size(); i++) {
          Bar* pBar = (Bar*) vResultBars.at(i);

          if (((GroupedBarChart*) pInitialChart)->GetConnectedBar(pBar->GetDataEntry()) == NULL) {
            vMissingDataElements.push_back(new Bar(pBar->GetDataEntry(),
              pBar->GetLeft(), pBar->GetTop(), pBar->GetBottom(), pBar->GetWidth()));
          }
        }

        break;
      }
      case STACKED_BAR: {
        std::vector<DataElement*> vResultBars = ((StackedBarChart*) pResultChart)->GetAllBars();

        for (unsigned int i = 0; i < vResultBars.size(); i++) {
          Bar* pBar = (Bar*) vResultBars.at(i);

          if (((StackedBarChart*) pInitialChart)->GetConnectedBar(pBar->GetDataEntry()) == NULL) {
            vMissingDataElements.push_back(new Bar(pBar->GetDataEntry(),
              pBar->GetLeft(), pBar->GetTop(), pBar->GetBottom(), pBar->GetWidth(), pBar->GetLabel()));
          }
        }

        break;
      }
      case PIE_SECTOR: {
        std::vector<PieSlice*> vResultSlices = ((PieChart*) pResultChart)->GetAllSlices();

        for (unsigned int i = 0; i < vResultSlices.size(); i++) {
          PieSlice* pSlice = vResultSlices.at(i);

          if (((PieChart*) pInitialChart)->GetConnectedSlice(pSlice->GetDataEntry()) == NULL) {
            vMissingDataElements.push_back(new PieSlice(pSlice->GetDataEntry(), pSlice->GetBeginValue(),
              1.0f));
          }
        }

        break;
      }
      default: {
        //this should not be possible
      }
    }
  }

  return vMissingDataElements;
}

Chart* FilteringTransition::GetActiveChart() {
  return pInitialChart;
}