#!/usr/bin/env python
# -----------------------------------------------------------------------
# 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.
# -----------------------------------------------------------------------

import os
import sys
import glob
import shutil
import subprocess

# Start by finding DUCC_HOME and and setting the python path so it can
# find the common code in DUCC_HOME/bin
# Infer DUCC_HOME from our location - assume we're running from one level below
me = os.path.abspath(__file__)    
ndx = me.rindex('/')
ndx = me.rindex('/', 0, ndx)
DUCC_HOME = me[:ndx]          # split from 0 to ndx
    
cwd = os.getcwd()
if cwd != DUCC_HOME+'/admin':
    print '>>> ERROR - this script must be run from the admin directory'
    sys.exit(99)

sys.path.append(DUCC_HOME + '/bin')
from ducc_base import DuccBase
from properties import Properties


def main():

    props = Properties()
    props.load('../resources/ducc.properties')
    java = props.get('ducc.jvm')
    print 'Using', java
    
    fn = '../lib/uima-ducc/uima-ducc-common*.jar'
    common_jar = glob.glob(fn)

    osarch = 'org.apache.uima.ducc.common.utils.OsArch'

    CMD = ' '.join([java, '-cp', common_jar[0], osarch])
    print CMD

    proc = subprocess.Popen(CMD, shell=True, bufsize=0, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    lines = []
    for  line in proc.stdout:
        lines.append(line.strip())
        proc.wait()
        rc = proc.returncode

    if ( rc != 0 ):
        print 'build_duccling: Cannot find java property os.arch. The following command failed:'
        print CMD
        sys.exit(1)

    arch = lines[0]
    print 'Os Architecture:', arch

    if ( not os.path.exists(arch) ):
        os.mkdir(arch)

    here = os.getcwd()
    os.chdir("../duccling/src")
    rc = os.system("make clean all")
    if ( rc != 0 ):
        print 'Cannot run "make" in ../duccling/src.  Insure you have a C compiler on this system.'
        sys.exit(1)
    os.chdir(here)

    shutil.copyfile("../duccling/src/ducc_ling",  arch + '/ducc_ling')
    os.chmod(arch + '/ducc_ling', 0755)

    CMD = ' '.join([arch + '/ducc_ling', '-v'])
    rc = os.system(CMD)
    if ( rc != 0 ):
        print 'Could not run', arch +'ducc_ling -v'

    print 'ducc_ling is installed for architecture', arch + '. See the installation guide for additional modifications needed to run user processes with their OS user credentials.'


main()
