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

/*
  <file> Css3Lex.cs </file>
  <brief>
    Tokenize and dump the css3 file.
  </brief>
  <author>
    Stanley Hong <link2next@gmail.com>, Dec. 2013.
  </author>
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using uls.collection;

//
// To generate the file 'Css3LexBasis.cs' from 'css3.ulc', use Ulc2Class.exe
//    Ulc2Class.exe -pCSS_ -lcs -o Css3LexBasis.cs -n uls.nemesis.Css3LexBasis css3.ulc
//

namespace uls
{
    namespace tests
    {
        namespace Css3Toks
        {
            public class Css3Lex : Css3LexBasis
            {
                StringBuilder tokbuf;

                String tok_str;
                int tok_id;
                bool tok_ungot;

                int prepare_url_tok;

                private bool is_digit(uint ch)
                {
                    bool rval;
                    rval = (ch >= '0' && ch <= '9') ? true : false;
                    return rval;
                }
 
                private int concat_lexeme(String str, int tok)
                {
                    base.getTok();

                    tokbuf.Append(str);
                    tokbuf.Append(base.TokStr);

                    return tokbuf.Length;
                }

                public Css3Lex(String config_name)
                    : base(config_name)
                {
                    tokbuf = new StringBuilder();
                    prepare_url_tok = 0;

                    tok_id = CSS_NONE;
                    tok_str = "";
                    tok_ungot = false;
                }

                public void setFile(String fpath)
                {
                    base.pushFile(fpath);
                }

                int get_token_internal()
                {
                    uint ch;
                    int tok, k;
                    int paren_lvl;
                    bool is_quote;

                    if (tok_ungot == true)
                    {
                        tok_ungot = false;
                        return tok_id;
                    }

                    if (prepare_url_tok == 2)
                    {
                        if ((ch = base.peekCh()) == NEXTCH_NONE)
                        {
                            tok = base.getTok();
                            is_quote = base.isQuoteTok(tok);
                            if (is_quote == false)
                            {
                                tok_str = "";
                                tok_id = CSS_ERR;
                                return tok_id;
                            }

                            // url('../../image/a.png')
                            tok_str = base.TokStr;

                            tok_id = CSS_PATH;
                            prepare_url_tok = 0;

                            return tok_id;
                        }

                        // url(../../image/a.png)
                        k = paren_lvl = 0;
                        tokbuf.Length = 0;

                        while (ch != ')' || paren_lvl > 0)
                        {
                            base.getCh();

                            tokbuf.Append((char)ch);
                            if (ch == '(') ++paren_lvl;
                            else if (ch == ')') --paren_lvl;

                            if ((ch = base.peekCh()) == NEXTCH_NONE)
                            {
                                break;
                            }
                        }

                        tok_str = tokbuf.ToString();
                        tok_id = CSS_PATH;
                        prepare_url_tok = 0;

                        return tok_id;
                    }

                    tok = base.getTok();

                    if (prepare_url_tok == 1)
                    {
                        expect('(');
                        prepare_url_tok = 2;
                    }
                    else if (tok == CSS_URL)
                    {
                        prepare_url_tok = 1;
                    }
                    else if (tok == '-')
                    {
                        ch = base.peekCh();
                        if (ch == '.' || is_digit(ch))
                        {
                            tok = CSS_NUM;
                            tokbuf.Length = 0;
                            concat_lexeme("-", tok);
                            tok_str = tokbuf.ToString();
                            tok_id = CSS_NUM;
                            return tok_id;

                        }
                        else if (base.isId(ch))
                        {
                            tok = CSS_ID;
                            tokbuf.Length = 0;
                            concat_lexeme("-", tok);
                            tok_str = tokbuf.ToString();
                            tok_id = CSS_ID;
                            return tok_id;
                        }
                    }

                    tok_str = base.TokStr;
                    tok_id = tok;

                    return tok_id;
                }

                public override int getTok()
                {
                    return get_token_internal();
                }
               
                public override void ungetTok()
                {
                    tok_ungot = true;
                }

                public override int TokNum
                {
                    get
                    {
                        return tok_id;
                    }
                }

                public override String TokStr
                {
                    get
                    {
                        return tok_str;
                    }
                }
            }
        }
    }
}

