// import express
var express = require('express');

// init express app
var app = express();

// tell express to use body parser
app.use(express.bodyParser());

// tell express to use cookie parser
app.use(express.cookieParser());

// define a global application object
var SERVER = {};

// define admin credentials
SERVER.credentials = {};

SERVER.credentials.user     = 'foo';
SERVER.credentials.pass     = 'bar';
SERVER.credentials.timeout  = 5 * 60 * 1000; // session timeout: 5 minutes
SERVER.credentials.tokens   = {};

SERVER.__initUsers =
[
  {
    "id": "1",
    "name": "Robin",
    "email": "robin@angularjs.de"
  },
  {
    "id": "2",
    "name": "Sascha",
    "email": "robin@angularjs.de"
  },
  {
    "id": "3",
    "name": "Phil",
    "email": "phil@angularjs.de"
  },
  {
    "id": "4",
    "name": "Basti",
    "email": "basti@killerprogrammiererbude.de"
  },
  {
    "id": "5",
    "name": "Martin",
    "email": "martin@nicht-der-semmelrogge.de"
  },
  {
    "id": "6",
    "name": "Schepp",
    "email": "schaepp@gmx.de"
  }
];

SERVER.__initProjects = [
  {
    "id": 1,
    "name": "Bugtracker",
    "description": "A Bugtracker that rocks!"
  },
  {
    "id": 2,
    "name": "Workshop",
    "description": "A Workshop full of AngularJS experts."
  }
];

SERVER.__initIssues = [
    {
        "id": 1,
        "name": "Läuft nicht",
        "projectId": 1,
        "tags": ["db", "ajax"]
    },

    {
        "id": 2,
        "name": "Geht nicht",
        "projectId": 2,
        "tags": ["foo", "bar"]
    },

    {
        "id": 3,
        "name": "Crasht immer",
        "projectId": 1,
        "tags": ["very", "such", "wow"]
    }
];

// some helper functions
SERVER.deepCopy = function(obj) {
    // quick and dirty deep copy
    return JSON.parse(JSON.stringify(obj));
};

// load default stuff
SERVER.reset = function() {
  SERVER._users = SERVER.deepCopy(SERVER.__initUsers);
  SERVER._projects = SERVER.deepCopy(SERVER.__initProjects);
  SERVER._issues = SERVER.deepCopy(SERVER.__initIssues);
}

SERVER.generateToken = function () {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
};

SERVER.tokenExpired = function(token, res) {
    var timestamp   = SERVER.credentials.tokens[token],
        now         = new Date().getTime(),
        expired     = !(timestamp && ( (now - timestamp) < SERVER.credentials.timeout ));

    if (token && !expired) {
        SERVER.credentials.tokens[token] = now;
    }

    return expired;
};

SERVER.auth = function(req, res, successFn) {
    var expired = SERVER.tokenExpired(
        req.get('X-XSRF-TOKEN') || req.cookies['XSRF-TOKEN'],
        res
    );

    if (!expired) {
        successFn();
    }
    else {
        res.statusCode = 401;
        res.send('Session expired!');
    }
};

/*
SERVER.getBookByIsbn = function (isbn) {
    for (var i = 0, n = SERVER._books.length; i < n; i++) {
        if (isbn === SERVER._books[i].isbn) {
            return SERVER._books[i];
        }
    }

    return null;
};
*/

/*
SERVER.getTags = function () {
    var obj = {},
        tag;

    for (var i = 0, n = SERVER._books.length; i < n; i++) {
        for (var j = 0, m = SERVER._books[i].tags.length; j < m; j++) {
            tag = SERVER._books[i].tags[j];
            if (!obj.hasOwnProperty(tag)) {
                obj[tag] = true;
            }
        }
    }

    return Object.keys(obj);
};
*/

/*
SERVER.updateBook = function(book) {
    for (var i = 0, n = SERVER._books.length; i < n; i++) {
        if (book.isbn === SERVER._books[i].isbn) {
            SERVER._books[i] = book;
            return book;
        }
    }

    return null;
};
*/

/*
SERVER.deleteBookByIsbn = function(isbn) {
    var i = SERVER._books.length;
    while (i--) {
        if (isbn === SERVER._books[i].isbn) {
            return SERVER._books.splice(i, 1);
        }
    }

    return null;
};
*/

// set cors headers for all requests
app.all('*', function (req, res, next) {
    console.log('*');
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type");
    res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    res.header("Access-Control-Allow-Credentials", "true"); // in correspondence with 'withCredentials' flag in XHR
                                                            // to make XHR send cookies with a CORS request
    next();
});

// define an API to allow to restore the default books
app.get('/api/reset', function (req, res) {
    reset();
    res.json(SERVER._books);
});

// define an API to allow a user login
app.post('/api/login', function (req, res) {
    var credentials = req.body;

    if (credentials.user
            && credentials.pass
            && credentials.user === SERVER.credentials.user
            && credentials.pass === SERVER.credentials.pass) {
        var token = SERVER.generateToken();
        SERVER.credentials.tokens[token] = new Date().getTime();
        res.cookie('XSRF-TOKEN', token);
        res.json(true);
    }
    else {
        res.statusCode = 401;
        res.send('Unauthorized');
    }
});

app.get('/api/ping', function (req, res) {
    SERVER.auth(req, res, function() {
        res.json(true);
    });
});

// define resources

app.get('/', function (req, res) {
    console.log('/');
    res.end();
});

app.get('/api', function (req, res) {
    console.log('/api');
    res.end();
});

app.get('/api/users', function (req, res) {
    console.log('/api/users');
    res.json(SERVER._users);
});

app.get('/api/projects', function (req, res) {
    console.log('/api/projects');
    res.json(SERVER._projects);
});

app.get('/api/issues', function (req, res) {
    console.log('/api/issues');
    res.json(SERVER._issues);
});

/*
app.get('/api/tags', function (req, res) {
    res.json(SERVER.getTags());
});
*/

/*
app.get('/api/books/:isbn', function (req, res) {
    var book = SERVER.getBookByIsbn(req.params.isbn);

    if (book) {
        res.json(book);
    }
    else {
        res.statusCode = 404;
        res.send('Book not found!');
    }
});

app.post('/api/books', function(req, res) {
    SERVER.auth(req, res, function() {
        SERVER._books.push(req.body);
        res.json(true);
    });
});

app.put('/api/books/:isbn', function(req, res) {
    SERVER.auth(req, res, function() {
        var book = SERVER.updateBook(req.body);

        if (book) {
            res.json(true);
        }
        else {
            res.statusCode = 404;
            res.send('Book not found!');
        }
    });
});

app.delete('/api/books/:isbn', function(req, res) {
    SERVER.auth(req, res, function() {
        var book = SERVER.deleteBookByIsbn(req.params.isbn);

        if (book) {
            res.json(true);
        }
        else {
            res.statusCode = 404;
            res.send('Book not found!');
        }
    });
});
*/

SERVER.reset();

// start listening
app.listen(process.env.PORT || 4730);
