// 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.
package com.cloud.consoleproxy.util;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

public class Region {
    private Rectangle bound;
    private List<Rectangle> rectList;

    public Region() {
        bound = new Rectangle(0, 0, 0, 0);
        rectList = new ArrayList<Rectangle>();
    }
    
    public Region(Rectangle rect) {
        bound = new Rectangle(rect.x, rect.y, rect.width, rect.height);
        rectList = new ArrayList<Rectangle>();
        rectList.add(rect);
    }
    
    public Rectangle getBound() {
        return bound;
    }
    
    public void clearBound() {
        assert(rectList.size() == 0);
        bound.x = bound.y = bound.width = bound.height = 0;
    }
    
    public List<Rectangle> getRectangles() {
        return rectList;
    }
    
    public boolean add(Rectangle rect) {
        if(bound.isEmpty()) {
            assert(rectList.size() == 0);
            bound.x = rect.x;
            bound.y = rect.y;
            bound.width = rect.width;
            bound.height = rect.height;
            
            rectList.add(rect);
            return true;
        }
        
        Rectangle rcInflated = new Rectangle(rect.x - 1, rect.y- 1, rect.width + 2, rect.height + 2);
        if(!bound.intersects(rcInflated))
            return false;

        for(Rectangle r : rectList) {
            if(r.intersects(rcInflated)) {
                if(!r.contains(rect)) {
                    enlargeBound(rect);
                    rectList.add(rect);
                    return true;
                }
            }
        }
        return false;
    }
    
    private void enlargeBound(Rectangle rect) {
        int boundLeft = Math.min(bound.x, rect.x);
        int boundTop = Math.min(bound.y, rect.y);
        int boundRight = Math.max(bound.x + bound.width, rect.x + rect.width);
        int boundBottom = Math.max(bound.y + bound.height, rect.y + rect.height);
        
        bound.x = boundLeft;
        bound.y = boundTop;
        bound.width = boundRight - boundLeft;
        bound.height = boundBottom - boundTop;
    }
}
