/*
 *Licensed to the Apache Software Foundation (ASF) under one
 *or more contributor license agreements.  See the NOTICE file
 *distributed with this work for additional information
 *regarding copyright ownership.  The ASF licenses this file
 *to you 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.
 */
#include <stdlib.h>
#include <pthread.h>
#include <sys/time.h>
#include <stdio.h>
#include <math.h>

#include "benchmark.h"

static const char * const BENCHMARK_NAME = "MUTEX";
static const double SAMPLE_FACTOR = 1;

struct benchmark {
	pthread_mutex_t mutex;
	math_service_pt math;
};

typedef struct thread_info {
	benchmark_pt benchmark;
	int nrOfSamples;
	unsigned int result;
	struct timeval begin;
	struct timeval end;
	unsigned int skips;
} thread_info_t;

static void benchmark_thread(thread_info_t *info);

celix_status_t benchmark_create(benchmark_pt *benchmark) {
	(*benchmark) = malloc(sizeof(struct benchmark));
	(*benchmark)->math = NULL;
	pthread_mutex_init(&(*benchmark)->mutex, NULL);
	return CELIX_SUCCESS;
}

celix_status_t benchmark_destroy(benchmark_pt benchmark) {
	free(benchmark);
	return CELIX_SUCCESS;
}

benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) {
	int i;
	pthread_t threads[nrOfThreads];
	thread_info_t infos[nrOfThreads];
	benchmark_result_t result;
	unsigned long elapsedTime = 0;

	result.skips =0;

	for (i = 0 ; i < nrOfThreads ; i += 1) {
		infos[i].benchmark = benchmark;
		infos[i].nrOfSamples = nrOfSamples;
		infos[i].skips = 0;
		infos[i].result = rand();
		pthread_create(&threads[i], NULL, (void *)benchmark_thread,  &infos[i]);
	}

	for (i = 0; i < nrOfThreads ; i += 1) {
		pthread_join(threads[i], NULL);
		elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec);
		result.skips += infos[i].skips;
	}

    unsigned int actualSamples = (nrOfSamples * nrOfThreads) - result.skips;
	result.averageCallTimeInNanoseconds = actualSamples == 0 ? NAN : ((double)elapsedTime * 1000) / (nrOfSamples * nrOfThreads);
	result.callFrequencyInMhz = ((double)(actualSamples * nrOfThreads) / elapsedTime);
	result.nrOfThreads = nrOfThreads;
	result.nrOfsamples = actualSamples;
    result.requestedNrOfSamples = (nrOfSamples * nrOfThreads);

	return result;
}

static void benchmark_thread(thread_info_t *info) {
	int i;

	gettimeofday(&info->begin, NULL);
	for (i = 0; i < info->nrOfSamples; i += 1) {
		pthread_mutex_lock(&info->benchmark->mutex);
		if (info->benchmark->math != NULL) {
			info->result = info->benchmark->math->calc(info->benchmark->math->handle, info->result, i);
		} else {
			info->skips += 1; //should not happen
		}
		pthread_mutex_unlock(&info->benchmark->mutex);
	}
	gettimeofday(&info->end, NULL);

}

char * benchmark_getName(benchmark_pt benchmark) {
	return (char *)BENCHMARK_NAME;
}

celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) {
	pthread_mutex_lock(&benchmark->mutex);
	benchmark->math = mathService;
	pthread_mutex_unlock(&benchmark->mutex);
	return CELIX_SUCCESS;
}

celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) {
	pthread_mutex_lock(&benchmark->mutex);
	if (benchmark->math == mathService) {
		benchmark->math = NULL;
	}
	pthread_mutex_unlock(&benchmark->mutex);
	return CELIX_SUCCESS;

}

double benchmark_getSampleFactor(benchmark_pt benchmark) {
	return SAMPLE_FACTOR;
}
