/*
 * Copyright 2009 Andrew Prunicki <prunand@iit.edu,prunicki@ociweb.com>
 * 
 * Licensed 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.
 */
package com.ociweb.jnb.protobuf;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.ociweb.jnb.db.Database;

public class ProtoBufServer {
    
    public static final int PORT = 8001;
    
    static final int START_MESSAGE = 0xFF;
    static final int GET_COURSE_INVENTORY = 1;
    static final int GET_COURSE = 2;
    static final int ADD_COURSE = 3;
    static final int DEL_COURSE = 4;

    public static void main(final String[] args) {
        Database db = new Database();
        final ServerSocket serverSocket;
        try {
            serverSocket = new ServerSocket(PORT);
        } catch (IOException e) {
            e.printStackTrace(System.err);
            throw new RuntimeException(e);
        }
        
        final ExecutorService executor = Executors.newCachedThreadPool();
        final ServerRunnable sr = new ServerRunnable(serverSocket, executor, db);
        final Thread t = new Thread(sr);
        
        System.out.println("Firing up the Protocol Buffer server. - Press <Enter> to terminate.");
        t.start();
        
        try {
            System.in.read();
        } catch (IOException e) {
            e.printStackTrace(System.err);
            System.exit(1);
        }
        
        t.interrupt();
        try {
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace(System.err);
            System.exit(1);
        }
        executor.shutdown();
    }
    
    private static class ServerRunnable implements Runnable {
        
        private final ServerSocket serverSocket;
        private final ExecutorService executor;
        private final Database db;
        
        public ServerRunnable(ServerSocket serverSocket, ExecutorService executor, Database db) {
            this.serverSocket = serverSocket;
            this.executor = executor;
            this.db = db;
        }

        @Override
        public void run() {
            while (!Thread.interrupted()) {
                Socket socket;
                try {
                    socket = serverSocket.accept();
                    final ConnectionHandler handler = new ConnectionHandler(socket, db);
                    executor.execute(handler);
                } catch (IOException e) {
                    if (!serverSocket.isClosed()) {
                        e.printStackTrace(System.err);
                    }
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}
