#include <vector>

#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/filler.hpp"
#include "caffe/layer.hpp"
#include "caffe/util/math_functions.hpp"
#include "caffe/vision_layers.hpp"

namespace caffe {

template <typename Dtype>
void ImageTestTransformLayer<Dtype>::LayerSetUp(const vector<Blob<Dtype>*>& bottom,
      vector<Blob<Dtype>*>* top) {
	cropsize = this->layer_param_.image_data_pair_param().cropsize();
	if(this->layer_param_.image_data_pair_param().has_cropsize_h()){
	cropsize_h=this->layer_param_.image_data_pair_param().cropsize_h();
	}
	else {
		cropsize_h=bottom[0]->height();
	}
	if(this->layer_param_.image_data_pair_param().has_cropsize_w()){
	cropsize_w=this->layer_param_.image_data_pair_param().cropsize_w();
	}
	else {
		cropsize_w=bottom[0]->width();
	}
	scale=this->layer_param_.image_data_pair_param().scale();
}

template <typename Dtype>
void ImageTestTransformLayer<Dtype>::Reshape(const vector<Blob<Dtype>*>& bottom,
      vector<Blob<Dtype>*>* top) {
	(*top)[0]->Reshape(bottom[0]->num(), bottom[0]->channels(), cropsize_h, cropsize_w);
}


template<typename Dtype>
void ImageTestTransformLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
		vector<Blob<Dtype>*>* top) {
	int h_off = 0, w_off = 0;
		int perturb=12;
		int num=bottom[0]->num();
		int channels = bottom[0]->channels();
		int height=bottom[0]->height();
		int width = bottom[0]->width();
		Dtype * top_data = (*top)[0]->mutable_cpu_data();
		const Dtype * bottom_data = bottom[0]->mutable_cpu_data();
		//wang:如果需要裁剪：
		if (cropsize) {
			if (Caffe::phase() == Caffe::TRAIN && true/*!crop_center*/) {
				h_off = rand() %(height - cropsize_h);
				w_off = rand() % (width - cropsize_w);
				h_off = (height-cropsize_h)/2+perturb/2-rand()%perturb;
				w_off = (width-cropsize_w)/2+perturb/2-rand() % perturb;
			} else {
				h_off = (height - cropsize_h) / 2;
				w_off = (width - cropsize_w) / 2;
			}
			bool mirror2=false;
			//wang:如果需要求镜像，复制镜像图片
			if (Caffe::phase() == Caffe::TRAIN&&mirror2 && rand() % 2) {
				// Copy mirrored version
				LOG(INFO) << "1";
				for (int id=0; id<num; id++) {
				  for (int c = 0; c < channels; ++c) {
					for (int h = 0; h < cropsize_h; ++h) {
						for (int w = 0; w < cropsize_w; ++w) {
							top_data[((id * channels + c) * cropsize_h + h) * cropsize_w
									+ cropsize_w - 1 - w] =128*scale-bottom_data[((id * channels + c) * height + h + h_off) * width + w + w_off]*scale;
						}
					}
				  }
				}
			} else {
				for (int id=0; id<num; id++) {
				  for (int c = 0; c < channels; ++c) {
					for (int h = 0; h < cropsize_h; ++h) {
						for (int w = 0; w < cropsize_w; ++w) {
							top_data[((id * channels + c) * cropsize_h + h) * cropsize_w
									+ w] = 128*scale-bottom_data[((id * channels + c) * height + h + h_off) * width + w + w_off]*scale;
						}
					}
				  }
				}
			}
		}
		//wang:如果不需要裁剪
		else {
			for (int id=0; id<num; id++) {
			  for (int c = 0; c < channels; ++c) {
				for (int h = 0; h < height; ++h) {
					for (int w = 0; w < width; ++w) {
						top_data[((id * channels + c) * height + h) * width + w] =
								128*scale-bottom_data[((id * channels + c) * height + h + h_off) * width + w + w_off]*scale;
					}
				}
			  }
			}
		}
}

template<typename Dtype>
void ImageTestTransformLayer<Dtype>::Forward_gpu(const vector<Blob<Dtype>*>& bottom,
		vector<Blob<Dtype>*>* top) {
	Forward_cpu(bottom, top);
}

template<typename Dtype>
void ImageTestTransformLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
		const vector<bool>& propagate_down, vector<Blob<Dtype>*>* bottom) {
	return;
}

template<typename Dtype>
void ImageTestTransformLayer<Dtype>::Backward_gpu(const vector<Blob<Dtype>*>& top,
		const vector<bool>& propagate_down, vector<Blob<Dtype>*>* bottom) {
	return;
}

INSTANTIATE_CLASS(ImageTestTransformLayer);

}  // namespace caffe
