#ifndef MY_IMAGE_T_H
#define MY_IMAGE_T_H


#include <iostream>
#include "funkce.h"


template<class T> class my_image_T
{

public:
        //metody
    //konstruktory:
    my_image_T(int Width=10,int Height=10);
    my_image_T(my_image * img);
    my_image_T(my_image_T * img);

    ~my_image_T();

    int Width();
    int Height();

    T get(int x,int y);
    T get(BOD bod);
    void set(int x, int y,T color);

    void clean_all();
    my_image * get_my_image();

    void nasob(my_image_T<T> * hodnota);

private:
    T **data;
    int width;
    int height;


    T ** alocate_mem();
    void delete_memory(T ** memory);


};//*/

///////////////////implementace

template <class T>
my_image_T<T>::my_image_T(int Width,int Height)
{
    //std::cout<<"volan konstruktor my_image_T !!\n";
    this->data=NULL;
    this->width=Width;
    this->height=Height;
    this->data=this->alocate_mem();
    this->clean_all();
}


template <class T>
my_image_T<T>::my_image_T(my_image * img)
{
   // std::cout<<"volan konstruktor my_image_T !!\n";
    this->data=NULL;
    this->width=img->Width();
    this->height=img->Height();
    this->data=this->alocate_mem();

    for(int x=0;x<this->width;x++)
        for(int y=0;y<this->height;y++)
            this->data[x][y]=(T)img->data[x][y];
}

template <class T>
my_image_T<T>::my_image_T(my_image_T * img)
{
    //std::cout<<"volan konstruktor my_image_T !!\n";
    this->data=NULL;
    this->width=img->Width();
    this->height=img->Height();
    this->data=this->alocate_mem();

    for(int x=0;x<this->width;x++)
        for(int y=0;y<this->height;y++)
            this->data[x][y]=(T)img->data[x][y];
}

template <class T>
my_image_T<T>::~my_image_T()
{
    //std::cout<<"volan desktriktor my_image_T !!\n";
    if(this->data!=NULL)
        this->delete_memory(this->data);
}






template <class T>
        my_image * my_image_T<T>::get_my_image(){
    uchar *dat=new uchar[this->width*this->height];
    int k=0;
    for(int j=0;j<this->height;j++){
        for(int i=0;i<this->width;i++){
            dat[k]=this->data[i][j];
            k++;
        }
    }

    my_image * ret=new my_image(dat,this->width,this->height);
    delete dat;
    return ret;
}


template <class T>
T **  my_image_T<T>::alocate_mem()
{
    //alokace pameti
    T** d=NULL;

    d=(T **)calloc((this->width),sizeof(T*));
    if(d==NULL){
        std::cout<<"NEMAM PAMET my_image\n";
        return NULL;
    }
    for(int i=0;i<this->width;i++){
        d[i]=NULL;
        d[i]=(T *)calloc(this->height,sizeof(T));
        if(d[i]==NULL)  {
            std::cout<<"NEMAM PAMET my_image\n";
            return NULL;
        }
    }
    return d;
}


template <class T>
void my_image_T<T>::delete_memory(T** memory)
{
    for(int i=0;i<this->width;i++)
        free (memory[i]);
    free(memory);
}

template <class T>
        int my_image_T<T>::Width(){
return this->width;
}

template <class T>
        int my_image_T<T>::Height(){
return this->width;
}

template <class T>
        T my_image_T<T>::get(BOD bod){
    return this->get(bod.x,bod.y);
}

template <class T>
        T my_image_T<T>::get(int x, int y){
    if(this->data==NULL){
        // throw "Neni nacten obraz, nemuzes pouzit metodu my_image.get()";
        std::cout<<"Neni nacten obraz, nemuzes pouzit metodu my_image.get() \n";
        return 0;
    }
    if(x<0 || x>=this->width){
       // throw "Sahas mimo obraz my_image.get() couradnice x";
        std::cout<<"Sahas mimo obraz my_image.get() couradnice x: "<<x<<"ale sirka je "<<this->width<<" \n";
        return 0;
    }

    if(y<0 || y>=this->height){
      //  throw "Sahas mimo obraz my_image.get() couradnice y";
        std::cout<<"Sahas mimo obraz my_image.get() couradnice y: "<<y<<"ale vyska je "<<this->height<<" \n";

        return 0;
    }
    return data[x][y];;
}

template <class T>
        void my_image_T<T>::set(int x, int y, T color){
    if(this->data==NULL){
        // throw "Neni nacten obraz, nemuzes pouzit metodu my_image.set()";
        std::cout<<"Neni nacten obraz, nemuzes pouzit metodu my_image.set() \n";
        return;
    }
    if(x<0 || x>=this->width){
       // throw "Sahas mimo obraz my_image.set() couradnice x";
        std::cout<<"Sahas mimo obraz my_image.set() couradnice x: "<<x<<"ale sirka je "<<this->width<<" \n";
        return;
    }

    if(y<0 || y>=this->height){
      //  throw "Sahas mimo obraz my_image.set() couradnice y";
        std::cout<<"Sahas mimo obraz my_image.set() couradnice y: "<<y<<"ale vyska je "<<this->height<<" \n";

        return;
    }
    data[x][y]=color;

}


template <class T>
        void my_image_T<T>::clean_all(){
            for(int x=0;x<this->width;x++)
                for(int y=0;y<this->height;y++)
                {
                    this->data[x][y]=0;
                }
}


template <class T>
        void my_image_T<T>::nasob(my_image_T<T> * hodnota){

    for(int x=0;x<this->width;x++)
        for(int y=0;y<this->height;y++)
        {
            this->data[x][y]=hodnota->data[x][y]*this->data[x][y];
        }
                //std::cout<<" a="<<a<<" b="<<b<<" c="<<c<<"\n";
}




#endif // MY_IMAGE_T_H
