/*
 * 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.thrift;

import java.io.IOException;
import java.util.List;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;

import com.ociweb.jnb.db.Database;
import com.ociweb.jnb.thrift.gen.Course;
import com.ociweb.jnb.thrift.gen.CourseNotFoundException;
import com.ociweb.jnb.thrift.gen.CourseService;
import com.ociweb.jnb.thrift.gen.UnacceptableCourseException;

public class ThriftServer {

    public static final int PORT = 8000;
    public static final String PROTOCOL_FLAG_COMPACT = "compact";
    public static final String PROTOCOL_FLAG_BINARY = "binary";
    
    private static final Database db = new Database();

    /**
     * @param args
     */
    public static void main(String[] args) {
        boolean compact = true;
        if (args.length > 0) {
            if (PROTOCOL_FLAG_BINARY.equalsIgnoreCase(args[0])) {
                compact = false;
            }
        }
        int retcode = 0;
        try {
            final TNonblockingServerSocket socket = new TNonblockingServerSocket(PORT);
            final CourseService.Processor processor = new CourseService.Processor(new Handler());
            final TProtocolFactory protocolFactory;
            if (compact) {
                protocolFactory = new TCompactProtocol.Factory();
            } else {
                protocolFactory = new TBinaryProtocol.Factory();
            }
            final TServer server = new THsHaServer(processor, socket,
                    new TFramedTransport.Factory(), protocolFactory);

            final Runnable runnable = new Runnable() {

                @Override
                public void run() {
                    server.serve();
                }
            };
            Thread t = new Thread(runnable);
            System.out.println("Firing up the Thrift server - Press <Enter> to terminate.");
            t.start();
            System.in.read();
        } catch (TTransportException e) {
            e.printStackTrace(System.err);
            retcode = 1;
        } catch (RuntimeException e) {
            e.printStackTrace(System.err);
            retcode = 1;
        } catch (IOException e) {
            e.printStackTrace(System.err);
            retcode = 1;
        } finally {
            System.out.println("Exiting Thrift server.");
        }
        
        System.exit(retcode);
    }
    
    public static class Handler implements CourseService.Iface {

        @Override
        public List<String> getCourseInventory() throws TException {
            return db.getCourseList();
        }

        @Override
        public Course getCourse(String courseNumber) throws CourseNotFoundException, TException {
            final com.ociweb.jnb.db.Course dbCourse = db.getCourse(courseNumber);
            if (dbCourse != null) {
                return ConversionHelper.fromDbCourse(dbCourse);
            }
            
            return null;
        }
        
        @Override
        public void addCourse(Course course) throws UnacceptableCourseException, TException {
            com.ociweb.jnb.db.Course dbCourse = ConversionHelper.toDbCourse(course);
            db.addCourse(dbCourse);
        }

        @Override
        public void deleteCourse(String courseNumber) throws CourseNotFoundException, TException {
            if (db.getCourse(courseNumber) != null) {
                db.deleteCourse(courseNumber);
            }
        }
    }
}
